Связать видимость текстового блока с пользовательским свойством сетки

Здравствуйте,

Прочитав множество тем о привязке видимости в течение нескольких часов, я спрашиваю здесь, потому что мне не удается заставить мое дело работать.

У меня есть сетка с настраиваемым присоединенным свойством (типа System.Windows.Visibily), которое я хочу использовать для отображения (или нет) текстового блока внутри сетки (путем привязки). Также я хочу изменить видимость каждый раз, когда изменяется пользовательское прикрепленное свойство.

Что я уже сделал: класс CustomProperties:

    public static class CustomProperties
    {
        public static readonly DependencyProperty starVisibilityProperty = 
            DependencyProperty.RegisterAttached("starVisibility", 
            typeof(System.Windows.Visibility), typeof(CustomProperties), 
            new FrameworkPropertyMetadata(null));

        public static System.Windows.Visibility GetStarVisibility(UIElement element)
        {
            if (element == null)
                throw new ArgumentNullException("element");
            return (System.Windows.Visibility)element.GetValue(starVisibilityProperty);
        }

        public static void SetStarVisibility(UIElement element, System.Windows.Visibility value)
        {
            if (element == null)
                throw new ArgumentNullException("element");
            element.SetValue(starVisibilityProperty, value);
        }
    }

Тогда вот мой xaml:

            <Grid Name="server1State" Grid.Row="1" local:CustomProperties.StarVisibility="Hidden">
                <TextBlock Name="server1Star" Text="&#xf005;" FontFamily="{StaticResource fa-solid}" FontSize="30" Margin="10" Foreground="#375D81" Visibility="{Binding ElementName=server1State, Path=server1State.(local:CustomProperties.starVisibility)}"/>
            </Grid>

Но когда я запускаю свое приложение, текстовый блок абсолютно не скрыт, он виден и никогда не меняется. Я пробовал много вещей с Path, а также с INotifyPropertyChanged, но, поскольку я работаю со статическим настраиваемым присоединенным свойством, мне не удалось заставить его работать.

Возможно, кто-то из вас мог бы мне помочь, спасибо.


person Gosfly    schedule 02.04.2020    source источник
comment
Есть ли причина, по которой вы используете пользовательское свойство, а не конвертер? Кроме того, почему свойство находится в сетке, а не в текстовом поле?   -  person Phoenix Stoneham    schedule 02.04.2020
comment
Мое пользовательское свойство сначала было логическим, и я хотел преобразовать его как видимость с помощью BooleanToVisibilityConverter во время привязки, но, поскольку я не нашел, как заставить его работать, я попытался удалить шаг преобразования. Но, конечно, я бы предпочел иметь логическое значение. И я хотел бы иметь свойство в сетке, потому что позже у меня будет много вещей внутри сетки, которые могут меняться в зависимости от значения свойства. Он станет государственной собственностью, которая будет преобразована конвертерами.   -  person Gosfly    schedule 02.04.2020
comment
Я предполагаю, что вы используете MVVM, если да, то почему бы вам вместо этого не предоставить набор свойств для различных состояний видимости, например. предполагая, что у вас есть крайний срок, статус счета и принятый статус — IsEditable, IsPassedDeadline и IsAccepted. Затем выполняйте свою бизнес-логику в виртуальной машине, а не в пользовательском свойстве.   -  person Phoenix Stoneham    schedule 02.04.2020


Ответы (1)


Ваш Binding.Path на TextBlock неверен.

Поскольку я прочитал из вашего комментария, что вы предпочитаете использовать логическое свойство, я покажу, как преобразовать значение bool в значение перечисления Visibility с помощью BooleanToVisibilityConverter. Я думаю, вы, возможно, уже поняли, но потом запутались из-за вашего неправильного Binding.Path:

CustomProperties.cs

public class CustomProperties : DependencyObject
{
  #region IsStarVisibile attached property

  public static readonly DependencyProperty IsStarVisibileProperty = DependencyProperty.RegisterAttached(
    "IsStarVisibile",
    typeof(bool),
    typeof(CustomProperties),
    new PropertyMetadata(default(bool)));

  public static void SetIsStarVisibile(DependencyObject attachingElement, bool value) => attachingElement.SetValue(CustomProperties.IsStarVisibileProperty, value);

  public static bool GetIsStarVisibile(DependencyObject attachingElement) => (bool)attachingElement.GetValue(CustomProperties.IsStarVisibileProperty);

  #endregion
}

MainWindow.xaml

<Window>
  <Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
  </Window.Resources>

  <Grid Name="Server1StateGrid"
        CustomProperties.IsStarVisibile="False">
    <TextBlock Text="&#xf005;" 
               Visibility="{Binding ElementName=Server1StateGrid,       
                            Path=(CustomProperties.IsStarVisibile), 
                            Converter={StaticResource BooleanToVisibilityConverter}}" />
  </Grid>
</Window>
person BionicCode    schedule 02.04.2020
comment
Привет, спасибо за ваш ответ !! У меня все еще есть ошибка, но я думаю, что мы почти ее получили, потому что я никогда не сталкивался с этим: когда я хочу запустить приложение, оно завершается с ошибкой XamlParseException => Предоставить значение для «System.Windows.Baml2006.TypeConverterMarkupExtension» вызвало исключение. ' Номер строки «88» и позиция строки «149». Это происходит, когда я добавляю Path и Converter - person Gosfly; 02.04.2020
comment
Это не удается, когда я добавляю путь, более того, мне пришлось написать (local:CustomProperties.IsStarVisible) - person Gosfly; 02.04.2020
comment
Да, пример должен быть общим. Пространства имен специфичны. Поэтому я оставил пространства имен. Конечно, вы должны квалифицировать каждый тип, используемый в XAML, чтобы синтаксический анализатор XAML мог разрешать типы. Что касается ошибки, добавили ли вы BooleanToVisibilityConverter к любому ResourceDictionary в пределах области действия? Пример определенно рабочий. - person BionicCode; 02.04.2020
comment
Да внутри Window.Resources, как и вы. Следующее компилируется хорошо {Binding ElementName=server1State, Converter={StaticResource BooleanToVisibilityConverter}}, оно дает сбой только при попытке добавить Path. - person Gosfly; 02.04.2020
comment
Ваша реализация прикрепленного свойства CustomProperties.IsStarVisibile выглядит точно так же, как моя? - person BionicCode; 02.04.2020
comment
Не могли бы вы просто скопировать мой приведенный выше код в чистый файл Window и запустить его? Я только что проверил это, и это работает. - person BionicCode; 02.04.2020
comment
Оно работает !! Ну наконец то !! Как вы предложили, я попытался запустить ваш код в чистом окне без его изменения (простая копия-вставка), и это сработало хорошо. Вероятно, я не смог адаптировать его к своему делу, потому что я все переименовал и т. Д. Большое спасибо! - person Gosfly; 02.04.2020
comment
Добро пожаловать. Это определенно сработает и в вашем контексте. Просто убедитесь, что все ссылки верны, включая имена элементов. - person BionicCode; 02.04.2020