最近我尝试制作标签样式,允许根据设置的属性显示图像或文本块。我已将正确的对象绑定到标签的DataContext,并为这些标签准备了可重用的样式。默认内容是使用Name作为文本的文本块,但如果IsIconSet属性为true,则内容将更改为具有相应IconPath作为源的图像。
类似的方法与标签的属性(如背景或光标)完美配合,但在描述的场景中,当IsIconSet在两个实例中具有相同的值时,它会中断。然后它不会显示第一个标签的内容,也不显示第二个标签的文本块/图像。
我试图将转换器附加到样式中的Name和IconPath绑定,以便检查传递的值,但似乎甚至没有在第一个标签上调用它。
有没有人设法做类似的事情?我错过了什么基本的东西?或许这种行为还有另一种方法吗? 任何帮助将不胜感激。
简化代码:
主窗口
<StackPanel DataContext="{Binding First}">
<Label Style="{StaticResource LabelStyle}" />
</StackPanel>
<StackPanel DataContext="{Binding Second}">
<Label Style="{StaticResource LabelStyle}" />
</StackPanel>
风格
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="{Binding Name}"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding IconPath}"/>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
类
public class ViewModel : INotifyPropertyChanged
{
private LabelClass _first;
private LabelClass _second;
public LabelClass First
{
get => _first;
set
{
_first = value;
OnPropertyChanged();
}
}
public LabelClass Second
{
get => _second;
set
{
_second = value;
OnPropertyChanged();
}
}
public ViewModel()
{
First = new LabelClass("First", "Resources/first.png");
Second = new LabelClass("Second", "Resources/second.png");
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class LabelClass : INotifyPropertyChanged
{
private string _name;
private string _iconPath;
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public string IconPath
{
get => _iconPath;
set
{
_iconPath = value;
OnPropertyChanged();
OnPropertyChanged("IsIconSet");
}
}
public bool IsIconSet => !string.IsNullOrEmpty(IconPath);
public LabelClass(string name, string iconPath = null)
{
Name = name;
IconPath = iconPath;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
答案 0 :(得分:0)
LabelStyle可以被多个标签使用,但TextBlock和Image from Content setter只创建一次,所有标签只有一个实例,但不能在多个地方显示。所以它只显示一个。
修复问题使用ContentTemplate,如下所示。
<Setter Property="Content" Value="{Binding}"/>
行表示整个DataContext被视为标签内容。在ContentTemplate
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content" Value="{Binding}"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{Binding IconPath}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
或者,将TextBlock和Image转换为非共享资源:
<Image Source="{Binding IconPath}" x:Key="Img" x:Shared="False"/>
<TextBlock Text="{Binding Name}" x:Key="Txt" x:Shared="False"/>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="Content" Value="{StaticResource Txt}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsIconSet}" Value="True">
<Setter Property="Content" Value="{StaticResource Img}"/>
</DataTrigger>
</Style.Triggers>
</Style>