Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Triggers Based on Properties from DataContext

Tags:

wpf

triggers

Suppose I want to show/hide elements based on Values of Properties from DataContext, how can I acheive it?

// In MainWindow.xaml.cs: DataContext of MainWindow.xaml
public int Mode { get; set; } 

In XAML, I want to show hide elements based on the Mode. How can I make the below work? Or what is the appropriate way of implementing this?

<StackPanel>
    <StackPanel.Triggers>
        <Trigger Property="Mode" Value="1">
            <Setter TargetName="txt1" Property="Visibility" Value="Visible" />
            <Setter TargetName="txt2" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="txt3" Property="Visibility" Value="Visible" />
        </Trigger>
        <Trigger Property="Mode" Value="2">
            <Setter TargetName="txt1" Property="Visibility" Value="Collapsed" />
            <Setter TargetName="txt2" Property="Visibility" Value="Visible" />
            <Setter TargetName="txt3" Property="Visibility" Value="Collapsed" />
        </Trigger>
    </StackPanel.Triggers>
    <TextBlock Text="TextBlock 1" x:Name="txt1" />
    <TextBlock Text="TextBlock 2" x:Name="txt2" />
    <TextBlock Text="TextBlock 3" x:Name="txt3" />
</StackPanel>

Currently, the Error I am getting is "Property 'Mode' was not found in type 'StackPanel'. D:\tmp\WpfApplication1\TriggersAndProperties\MainWindow.xaml"

like image 443
Jiew Meng Avatar asked Nov 28 '10 08:11

Jiew Meng


2 Answers

You need to use DataTriggers if you want triggers that can work on bindings. Problem is, DataTriggers are only available on style and template so you need to define one like this:

<StackPanel>
  <StackPanel.Style>
    <Style TargetType="{x:Type StackPanel}">
      <Style.Triggers>
        <DataTrigger Binding="{Binding Path=Mode}" Value="1">
          <Setter TargetName="txt1" Property="Visibility" Value="Visible" />
          <Setter TargetName="txt2" Property="Visibility" Value="Collapsed" />
          <Setter TargetName="txt3" Property="Visibility" Value="Visible" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=Mode}" Value="2">
          <Setter TargetName="txt1" Property="Visibility" Value="Collapsed" />
          <Setter TargetName="txt2" Property="Visibility" Value="Visible" />
          <Setter TargetName="txt3" Property="Visibility" Value="Collapsed" />
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </StackPanel.Style>
  <TextBlock Text="TextBlock 1" x:Name="txt1" />
  <TextBlock Text="TextBlock 2" x:Name="txt2" />
  <TextBlock Text="TextBlock 3" x:Name="txt3" />
</StackPanel>

Another solution would be to use an IValueConverter that converts the int from Mode to the Visibility you want, and apply it directly to each text block Visibility property.

Note that Dean Chalk's answer stays valid: you have to use a DependencyProperty or implement INotifyPropertyChanged if you want changes on Mode to trigger.

like image 107
Julien Lebosquain Avatar answered Oct 18 '22 12:10

Julien Lebosquain


Your propert 'Mode' needs to be a dependency property in order to be used this way:

public class MainViewModel : DependencyObject
{
    readonly DependencyProperty ModeProperty = DependencyProperty
        .Register("Mode", typeof(int), typeof(MainViewModel));

    public int Mode
    {
        get { return (int) GetValue(ModeProperty); }
        set { SetValue(ModeProperty, value); }
    }
}
like image 2
Dean Chalk Avatar answered Oct 18 '22 10:10

Dean Chalk