问题
My application shows a TreeView on the left with hierarchical ordered items which are all the same type. All the items have a dependency property which can have one of two values. This value is an enum. Depending on this value I want to show one of two UserControls on the left. My idea was to insert both controls and set their opacity to 0. Then I wanted to insert a Style with a DataTrigger that triggers the opacity depending on the enum's value. But I can not access the properties of one control from the other control's DataTrigger; and the trigger does not seem to recognize the enum's value.
The enum:
public enum IdentityType
{
Person,
OrganisationUnit
}
The XAML:
<TreeView Grid.Column="0" Grid.Row="1" Background="AntiqueWhite" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" ItemsSource="{Binding Identities}" x:Name="OiTree">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Childs}">
<TextBlock Text="{Binding}"/>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<Controls:UcPerson Grid.Column="1" Grid.Row="1" Opacity="0">
<Controls:UcPerson.Style>
<Style TargetType="Controls:UcPerson">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Type, ElementName=OiTree.SelectedItem}" Value="Person">
<Setter Property="Opacity" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Controls:UcPerson.Style>
</Controls:UcPerson>
<Controls:UcOrgUnit Grid.Column="1" Grid.Row="1" Opacity="0">
<Controls:UcOrgUnit.Style>
<Style TargetType="Controls:UcOrgUnit">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Type, ElementName=OiTree.SelectedItem}" Value="OrganisationUnit">
<Setter Property="Opacity" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Controls:UcOrgUnit.Style>
</Controls:UcOrgUnit>
回答1:
The problem is that you are setting the Opacity
directly on the control first.
An explicit setting on a control will always override a trigger value.
However, a trigger value will override a style setter.
The following code should work (though I haven't tested it myself)
<Controls:UcPerson Grid.Column="1" Grid.Row="1">
<Controls:UcPerson.Style>
<Style TargetType="Controls:UcPerson">
<Style.Setters>
<Setter Property="Opacity" Value="0" />
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Type, ElementName=OiTree.SelectedItem}" Value="Person">
<Setter Property="Opacity" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Controls:UcPerson.Style>
See this question here for another example of the problem: DataTrigger not firing
As an aside, I believe your problem could be solved more elegantly using a DataTemplateSelector.
回答2:
As Andrew implied the solution to my problem was a DataTemplateSelector. Instead of two userControls I created two templates and Used a ContentControl. The content Property of the ContentControl is bound to the SelectedItem of the TreeView and I implemented a simple DataTemplateSelector which casts the content to the original object an decides wich template to use. The source (modified) is from here: link
This is the xaml:
<Window.Resources>
<DataTemplate x:Key="borderTemplate">
<Border BorderThickness="1" BorderBrush="Brown" CornerRadius="5">
<TextBlock Margin="5" Text="Border Template"/>
</Border>
</DataTemplate>
<DataTemplate x:Key="twoTextBlockTemplate">
<StackPanel>
<TextBlock Margin="5" Text="First TextBlock"/>
<TextBlock Margin="5" Text="Second TextBlock"/>
</StackPanel>
</DataTemplate>
<vm:OiContentTemplateSelector
x:Key="myContentTemplateSelector"
BorderTemplate="{StaticResource borderTemplate}"
TwoTextBlockTemplate="{StaticResource twoTextBlockTemplate}"/>
</Window.Resources>
This is the DataTemplateSelector:
public class OiContentTemplateSelector : DataTemplateSelector
{
public DataTemplate BorderTemplate
{ get; set; }
public DataTemplate TwoTextBlockTemplate
{ get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
OrganisationIdentity value = item as OrganisationIdentity;
if (value != null)
{
if (value.Type == IdentityType.Person)
return BorderTemplate;
else if (value.Type == IdentityType.OrganisationUnit)
return TwoTextBlockTemplate;
return base.SelectTemplate(item, container);
}
else
return base.SelectTemplate(item, container);
}
}
Perhaps this helps somebody
来源:https://stackoverflow.com/questions/17059120/change-wpf-usercontrol-depending-on-a-property-of-a-treeviewitem