In the application on which I'm working I have couple of items which I monitor. Every item has several states (on, off, change). States are saved in model and DataContext of window is set to it. Every button DataContext is set to single item in SortableBindingList. In the XAML I have created Control Template for button and in DataTrigerrs in it. However, sometimes item only shows for first button, sometimes only for first three buttons (depending on what content I put inside DataTrigger). When I check in Snoop I see that all three buttons have correct DataContext set and there are no binding errors. I expect that every button shows it's content depending on value of 'serverstate' property however this does not happen. What am I doing wrong?
Control Template goes to Window.Resources:
<ControlTemplate x:Key="buttonTemplate" TargetType="Button" >
<Border BorderThickness="1"
BorderBrush="Gray"
Margin="2"
Width="40" Height="35"
>
<Border.Background>
<SolidColorBrush Color="Brown" />
</Border.Background>
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding serverstate}" Value="0">
<Setter Property="Content">
<Setter.Value>
<TextBlock Name="a1" Text="OFF" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding serverstate}" Value="1">
<Setter Property="Content">
<Setter.Value>
<TextBlock Name="a2" Text="CHNG" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding serverstate}" Value="2">
<Setter Property="Content">
<Setter.Value>
<TextBlock Name="a3" Text="ON" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" />
</Setter.Value>
</Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Buttons:
<Button Name="state1"
DataContext="{Binding ActiveServers[0]}"
Template="{StaticResource buttonTemplate}"
/>
<Button Name="state2"
DataContext="{Binding ActiveServers[1]}"
Template="{StaticResource buttonTemplate}"
/>
<Button Name="state3"
DataContext="{Binding ActiveServers[2]}"
Template="{StaticResource buttonTemplate}"
/>
<Button Name="state4"
DataContext="{Binding ActiveServers[3]}"
Template="{StaticResource buttonTemplate}"
/>
<Button Name="state5"
DataContext="{Binding ActiveServers[4]}"
Template="{StaticResource buttonTemplate}"
/>
This is how buttons shows up in window:
Notice how button 4 and 5 completely ignore property value in datacontext.
Model:
public class Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public Model()
{
}
private SortableBindingList<Server> _activeServers;
public SortableBindingList<Server> ActiveServers
{
get {
if (_activeServers == null)
{
_activeServers = new SortableBindingList<Server>();
}
return _activeServers;
}
set
{
_activeServers = value;
OnPropertyChanged("serverList");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
I think the problem is, that two buttons cann't use same Content
. So each type of Content
appears one time for each trigger value. You can avoid this by using ContentTemplate
.
So the code should look like this (same for other DataTriggers
). It allows you to change DataTemplates
to more complicated later.
<DataTrigger Binding="{Binding serverstate}" Value="2">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="ON" VerticalAlignment="Center"
HorizontalAlignment="Center" Foreground="White" />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>