WPF UserControl 公开子控件的属性以进行绑定
WPF UserControl exposing properties of subcontrols for binding
我正在为我的应用程序开发自定义用户控件。这个控件非常简单。它只是一个网格,在 [0,0] 中有一个复选框,在 [0,1] 中有一个 TextBlock。我在 XAML.
中按照自己喜欢的方式设计它没有遇到任何问题
然而,第二步却给我带来了一些麻烦。我正在尝试公开 IsChecked 布尔值?我的子控件是一个用于绑定到我的主窗体上的复选框,与 TextBlock.
的文本 属性 的想法相同
我尝试了几种不同的方法来解决这个问题,但都无济于事。
这是我的通用代码:
public partial class CDCheckBox : UserControl
{
public bool? IsChecked
{
get { return chk.IsChecked; }
set { chk.IsChecked = value; }
}
public string Text
{
get { return lbl.Text; }
set { lbl.Text = value; }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register(
"IsChecked",
typeof(bool?),
typeof(CDCheckBox),
new PropertyMetadata(default(bool?), OnItemsPropertyChanged));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(CDCheckBox),
new PropertyMetadata(default(string), OnItemsPropertyChanged));
/*
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
*/
private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// AutocompleteTextBox source = d as AutocompleteTextBox;
// Do something...
//lbl.Text = e.NewValue.ToString();
}
/*
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
*/
public CDCheckBox()
{
InitializeComponent();
}
}
当我 运行 上面的代码时,我没有收到任何错误,但我的绑定数据没有显示在我的 TextBlock 控件中。当我在写依赖属性之前尝试时,它在我的 XAML 中给了我一个错误,说 "A 'Binding' cannot be set on the 'IsChecked' property of type 'CDCheckBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."
然而有趣的是,这个错误并没有出现在构造函数中,而是出现在我编写的 window_loaded 方法中。然而,这似乎是一个转移注意力的问题,就好像我注释掉了该代码一样,在表单可以显示 XAMLParse Error.
之前它仍然失败
根据我的评论,您可以尝试设置具有您需要的 属性 类型的现有控件的样式。例如,在您的自定义控件中,您有一个可为 null 的布尔值 属性 和一个字符串 属性。如果重新调整 CheckBox
控件的用途,它已经有一个可为 null 的布尔值 属性 (IsChecked
) 和一个对象 属性 (Content
),可用于保存一个字符串。
您可以按照以下方式重新设置 CheckBox
控件的样式并更改其模板以获得您想要的结果:
<Window x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style x:Key="MySuperCheckboxStyle"
TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{TemplateBinding IsChecked}"
Content="Whatever you need here" />
<TextBlock Grid.Column="1"
Text="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox IsChecked="True"
Content="Unstyled check box"
Margin="10" />
<CheckBox Style="{StaticResource MySuperCheckboxStyle}"
IsChecked="True"
Content="Styled check box"
Margin="10" />
</StackPanel>
</Window>
这里的关键是 TemplateBinding
控件模板中使用的绑定。它们不像普通数据绑定那样绑定到数据上下文,而是绑定到被模板化的控件的属性。
每当您发现自己想要在 WPF 中创建自定义控件时,都值得探索是否可以使用现有控件并更改其外观以满足您的需要,因为这通常比创建新控件更省事(另一方面,并不总是可以重新调整现有控件的用途,尤其是当您需要不同的行为时)。
我正在为我的应用程序开发自定义用户控件。这个控件非常简单。它只是一个网格,在 [0,0] 中有一个复选框,在 [0,1] 中有一个 TextBlock。我在 XAML.
中按照自己喜欢的方式设计它没有遇到任何问题然而,第二步却给我带来了一些麻烦。我正在尝试公开 IsChecked 布尔值?我的子控件是一个用于绑定到我的主窗体上的复选框,与 TextBlock.
的文本 属性 的想法相同我尝试了几种不同的方法来解决这个问题,但都无济于事。
这是我的通用代码:
public partial class CDCheckBox : UserControl
{
public bool? IsChecked
{
get { return chk.IsChecked; }
set { chk.IsChecked = value; }
}
public string Text
{
get { return lbl.Text; }
set { lbl.Text = value; }
}
public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.Register(
"IsChecked",
typeof(bool?),
typeof(CDCheckBox),
new PropertyMetadata(default(bool?), OnItemsPropertyChanged));
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(CDCheckBox),
new PropertyMetadata(default(string), OnItemsPropertyChanged));
/*
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
*/
private static void OnItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// AutocompleteTextBox source = d as AutocompleteTextBox;
// Do something...
//lbl.Text = e.NewValue.ToString();
}
/*
public event PropertyChangedEventHandler PropertyChanged;
private void OnNotify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
*/
public CDCheckBox()
{
InitializeComponent();
}
}
当我 运行 上面的代码时,我没有收到任何错误,但我的绑定数据没有显示在我的 TextBlock 控件中。当我在写依赖属性之前尝试时,它在我的 XAML 中给了我一个错误,说 "A 'Binding' cannot be set on the 'IsChecked' property of type 'CDCheckBox'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject."
然而有趣的是,这个错误并没有出现在构造函数中,而是出现在我编写的 window_loaded 方法中。然而,这似乎是一个转移注意力的问题,就好像我注释掉了该代码一样,在表单可以显示 XAMLParse Error.
之前它仍然失败根据我的评论,您可以尝试设置具有您需要的 属性 类型的现有控件的样式。例如,在您的自定义控件中,您有一个可为 null 的布尔值 属性 和一个字符串 属性。如果重新调整 CheckBox
控件的用途,它已经有一个可为 null 的布尔值 属性 (IsChecked
) 和一个对象 属性 (Content
),可用于保存一个字符串。
您可以按照以下方式重新设置 CheckBox
控件的样式并更改其模板以获得您想要的结果:
<Window x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<Style x:Key="MySuperCheckboxStyle"
TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column="0"
IsChecked="{TemplateBinding IsChecked}"
Content="Whatever you need here" />
<TextBlock Grid.Column="1"
Text="{TemplateBinding Content}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox IsChecked="True"
Content="Unstyled check box"
Margin="10" />
<CheckBox Style="{StaticResource MySuperCheckboxStyle}"
IsChecked="True"
Content="Styled check box"
Margin="10" />
</StackPanel>
</Window>
这里的关键是 TemplateBinding
控件模板中使用的绑定。它们不像普通数据绑定那样绑定到数据上下文,而是绑定到被模板化的控件的属性。
每当您发现自己想要在 WPF 中创建自定义控件时,都值得探索是否可以使用现有控件并更改其外观以满足您的需要,因为这通常比创建新控件更省事(另一方面,并不总是可以重新调整现有控件的用途,尤其是当您需要不同的行为时)。