在 ItemsControl 中显示自定义项
Displaying customised Item in ItemsControl
我创建了一个(稍微)扩展的复选框,它有一个 IsError 属性(主要用于在不满足某些条件时将复选框的颜色更改为红色),如下所示:
public class MyCheckBox : CheckBox
{
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(MyCheckBox), new UIPropertyMetadata(false));
public MyCheckBox() : base()
{
IsError = false;
IsCorrect = false;
}
public bool IsError
{
get { return (bool)GetValue(IsErrorProperty); }
set { SetValue(IsErrorProperty, value); }
}
}
此控件与以下样式关联:
<Style TargetType="{x:Type local:MyCheckBox}">
<Setter Property="FontSize" Value="14"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,2,8,2"/>
<Setter Property="BorderBrush" Value="Yellow"/>
<Setter Property="BorderThickness" Value="2"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
<Trigger Property="IsError" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
一切正常,如果我创建这些复选框之一,它会正确响应 IsError 绑定。
我遇到的问题是将它们放在 ItemsControl 中时。如果我创建一个非常基本的项目控件并手动设置值,那么它就可以工作 - 显示项目列表并且 IsError 和 IsChecked 属性按预期运行。
<ItemsControl Grid.Column="3" Grid.Row="8" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0">
<local:MyCheckBox Content="Item1"/>
<local:MyCheckBox Content="Item2" IsChecked="True"/>
<local:MyCheckBox Content="Item3" IsError="True"/>
<local:MyCheckBox Content="Item4" IsChecked="True" IsError="True"/>
</ItemsControl>
但是,如果我对项目列表使用绑定,那么 Content 和 IsChecked 属性将按预期工作,但 IsError 属性 被完全忽略,我无法将边框更改为红色。
<ItemsControl Grid.Column="3" Grid.Row="8" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0">
ItemsSource="{Binding MyThings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:MyCheckBox Content="{Binding Path=ColorName}" IsChecked="{Binding Path=IsPresent}" IsError="{Binding Path=IsError}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我知道 IsError 绑定值是正确的(我通过包含绑定到显示正确 True/False 信息的相同值的标签进行测试)但我不知道如何显示自定义复选框适当地;就好像显示的项目使用的是标准复选框而不是自定义版本。
供参考,控件绑定的项目列表如下:
public class Thing : INotifyPropertyChanged
{
#region INotifyPropertyChanged
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private string colorName;
public string ColorName
{
get { return colorName; }
set { colorName = value; RaisePropertyChanged("ColorName"); }
}
private bool isPresent;
public bool IsPresent
{
get { return isPresent; }
set { isPresent = value; RaisePropertyChanged("IsPresent"); }
}
private bool isError;
public bool IsError
{
get { return isError; }
set { isError = value; RaisePropertyChanged("IsError"); }
}
public CastorClip(string colorName)
{
ColorName = colorName;
IsPresent = false;
IsError = false;
}
}
private ObservableCollection<Thing> myThings = new ObservableCollection<Thing>();
public ObservableCollection<Thing> MyThings
{
get { return myThings; }
set { myThings = value; RaisePropertyChanged("MyThings"); }
}
我错过了什么?我怎样才能使这项工作?
事实证明,自定义复选框的构造函数存在问题,其中 IsError 属性 被设置为覆盖绑定表达式。我也会在这里列出其他可能性,以便其他确实陷入 WPF 常见陷阱的人可以立即检查它们。
属性 IsError默认没有绑定两种方式,改成:
new UIPropertyMetadata(false)
至:
new FrameworkPropertyMetadata {
BindsTwoWayByDefault = true,
DefaultValue = false
}
此外,将其添加到您的复选框的静态构造函数中,以便它会寻找特定于您的复选框的默认样式:
static MyCheckBox ()
{
DefaultStyleKeyProperty.OverrideMetadata (typeof (MyCheckBox), new FrameworkPropertyMetadata (typeof (MyCheckBox)));
}
请务必检查资源是如何添加到您的应用中的。
我创建了一个(稍微)扩展的复选框,它有一个 IsError 属性(主要用于在不满足某些条件时将复选框的颜色更改为红色),如下所示:
public class MyCheckBox : CheckBox
{
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(MyCheckBox), new UIPropertyMetadata(false));
public MyCheckBox() : base()
{
IsError = false;
IsCorrect = false;
}
public bool IsError
{
get { return (bool)GetValue(IsErrorProperty); }
set { SetValue(IsErrorProperty, value); }
}
}
此控件与以下样式关联:
<Style TargetType="{x:Type local:MyCheckBox}">
<Setter Property="FontSize" Value="14"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,2,8,2"/>
<Setter Property="BorderBrush" Value="Yellow"/>
<Setter Property="BorderThickness" Value="2"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="BorderThickness" Value="0"/>
</Trigger>
<Trigger Property="IsError" Value="True">
<Setter Property="BorderBrush" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
一切正常,如果我创建这些复选框之一,它会正确响应 IsError 绑定。
我遇到的问题是将它们放在 ItemsControl 中时。如果我创建一个非常基本的项目控件并手动设置值,那么它就可以工作 - 显示项目列表并且 IsError 和 IsChecked 属性按预期运行。
<ItemsControl Grid.Column="3" Grid.Row="8" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0">
<local:MyCheckBox Content="Item1"/>
<local:MyCheckBox Content="Item2" IsChecked="True"/>
<local:MyCheckBox Content="Item3" IsError="True"/>
<local:MyCheckBox Content="Item4" IsChecked="True" IsError="True"/>
</ItemsControl>
但是,如果我对项目列表使用绑定,那么 Content 和 IsChecked 属性将按预期工作,但 IsError 属性 被完全忽略,我无法将边框更改为红色。
<ItemsControl Grid.Column="3" Grid.Row="8" HorizontalAlignment="Left" VerticalAlignment="Top" BorderThickness="0">
ItemsSource="{Binding MyThings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:MyCheckBox Content="{Binding Path=ColorName}" IsChecked="{Binding Path=IsPresent}" IsError="{Binding Path=IsError}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我知道 IsError 绑定值是正确的(我通过包含绑定到显示正确 True/False 信息的相同值的标签进行测试)但我不知道如何显示自定义复选框适当地;就好像显示的项目使用的是标准复选框而不是自定义版本。
供参考,控件绑定的项目列表如下:
public class Thing : INotifyPropertyChanged
{
#region INotifyPropertyChanged
protected void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private string colorName;
public string ColorName
{
get { return colorName; }
set { colorName = value; RaisePropertyChanged("ColorName"); }
}
private bool isPresent;
public bool IsPresent
{
get { return isPresent; }
set { isPresent = value; RaisePropertyChanged("IsPresent"); }
}
private bool isError;
public bool IsError
{
get { return isError; }
set { isError = value; RaisePropertyChanged("IsError"); }
}
public CastorClip(string colorName)
{
ColorName = colorName;
IsPresent = false;
IsError = false;
}
}
private ObservableCollection<Thing> myThings = new ObservableCollection<Thing>();
public ObservableCollection<Thing> MyThings
{
get { return myThings; }
set { myThings = value; RaisePropertyChanged("MyThings"); }
}
我错过了什么?我怎样才能使这项工作?
事实证明,自定义复选框的构造函数存在问题,其中 IsError 属性 被设置为覆盖绑定表达式。我也会在这里列出其他可能性,以便其他确实陷入 WPF 常见陷阱的人可以立即检查它们。
属性 IsError默认没有绑定两种方式,改成:
new UIPropertyMetadata(false)
至:
new FrameworkPropertyMetadata {
BindsTwoWayByDefault = true,
DefaultValue = false
}
此外,将其添加到您的复选框的静态构造函数中,以便它会寻找特定于您的复选框的默认样式:
static MyCheckBox ()
{
DefaultStyleKeyProperty.OverrideMetadata (typeof (MyCheckBox), new FrameworkPropertyMetadata (typeof (MyCheckBox)));
}
请务必检查资源是如何添加到您的应用中的。