Binding a Trigger to a custom property in a UserControl

Knox 26 Reputation points
2020-11-16T20:55:08.787+00:00

I have a StackPanel with a handful of custom UserControls (MyUserControl). I'm trying to write a style trigger that will hide MyUserControls if their CustomObject dependency property has IsEnabled set to False.

For example, with no style...

<StackPanel>

    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[0]" />
    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[1]" />
    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[2]" />

</StackPanel>

And the gist of what I'm wanting to have happen, but I know this code isn't correct...

<StackPanel>
    <StackPanel.Resources>

        <Style TargetType="{x:Type controls:MyUserControl}">

            <Style.Triggers>

                 <DataTrigger Binding="{Binding Path=CustomObject.IsEnabled}" Value="False">

                    <Setter Property="Visibility" Value="Collapsed" />

                 </DataTrigger>

            </Style.Triggers>

        </Style>

    </StackPanel.Resources>

    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[0]" />
    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[1]" />
    <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[2]" />

</StackPanel>
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,762 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. DaisyTian-1203 11,621 Reputation points
    2020-11-17T02:50:48.033+00:00

    You can try below code to replace your DataTrigger:

    <Style TargetType="{x:Type controls:MyUserControl}">  
                <Style.Triggers>  
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=(controls:MyUserControl.CustomObject)}" Value="False">  
                        <Setter Property="Visibility" Value="Collapsed" />  
                    </DataTrigger>  
                </Style.Triggers>  
            </Style>  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

  2. Peter Fleischer (former MVP) 19,321 Reputation points
    2020-11-17T05:34:38.083+00:00

    Hi,
    with following demo I cannot reproduce your problem. Please, show more details.

    XAML Main Window:

    <Window x:Class="WpfApp1.MainWindow"  
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
            xmlns:local="clr-namespace:WpfApp1"  
            xmlns:controls="clr-namespace:WpfControlLibrary1;assembly=WpfControlLibrary1"  
            mc:Ignorable="d"  
            Title="MainWindow" Height="450" Width="800">  
      <Window.DataContext>  
        <local:ViewModel/>  
      </Window.DataContext>  
      <StackPanel>  
        <StackPanel.Resources>  
          <Style TargetType="{x:Type controls:MyUserControl}">  
            <Style.Triggers>  
              <DataTrigger Binding="{Binding Path=CustomObject.IsEnabled}" Value="False">  
                <Setter Property="Visibility" Value="Collapsed" />  
              </DataTrigger>  
            </Style.Triggers>  
          </Style>  
        </StackPanel.Resources>  
        <CheckBox Content="Visibility" IsChecked="{Binding Path=CustomObject.IsEnabled}"/>  
        <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[0]}" />  
        <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[1]}" />  
        <controls:MyUserControl CustomObject="{Binding Path=CustomObjects[2]}" />  
      </StackPanel>  
    </Window>  
    

    Classes:

    using System.ComponentModel;  
    using System.Runtime.CompilerServices;  
      
    namespace WpfApp1  
    {  
      class ViewModel  
      {  
        public Data1 CustomObject { get; set; } = new Data1();  
        public Data2 CustomObjects { get; set; } = new Data2();  
      }  
      
      public class Data1 : INotifyPropertyChanged  
      {  
        private bool _isEnabled = true;  
        public bool IsEnabled  
        {  
          get => this._isEnabled;  
          set { this._isEnabled = value; OnPropertyChanged(); }  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
        private void OnPropertyChanged([CallerMemberName] string propName = "") =>  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));  
      }  
      public class Data2  
      {  
        private string[] arr = new string[3] { "test string 1", "test string  2", "test string    3" };  
      
        public string this[int i]  
        {  
          get { return arr[i]; }  
          set { arr[i] = value; }  
        }  
      }  
    }  
    

    XAML UserControl:

    <UserControl x:Class="WpfControlLibrary1.MyUserControl"  
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"   
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"   
                 xmlns:local="clr-namespace:WpfControlLibrary1"  
                 mc:Ignorable="d"   
                 d:DesignHeight="100" d:DesignWidth="800">  
      <Border x:Name="bo" BorderBrush="Red" BorderThickness="2" Margin="3" Width="100" HorizontalAlignment="Left">  
        <TextBlock Text="{Binding CustomObject}"/>  
      </Border>  
    </UserControl>  
    

    CodeBehind UserControl:

    using System;  
    using System.Windows;  
    using System.Windows.Controls;  
      
    namespace WpfControlLibrary1  
    {  
      public partial class MyUserControl : UserControl  
      {  
        public MyUserControl()  
        {  
          InitializeComponent();  
          this.bo.DataContext = this;  
        }  
      
        public static readonly DependencyProperty CustomObjectProperty =  
            DependencyProperty.RegisterAttached("CustomObject", typeof(object),  
              typeof(MyUserControl), new PropertyMetadata(null));  
      
        public static object GetCustomObject(DependencyObject obj) => obj.GetValue(CustomObjectProperty);  
        public static void SetCustomObject(DependencyObject obj, Object value) => obj.SetValue(CustomObjectProperty, value);  
      }  
    }  
    

    Result:

    40200-x.gif

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.