在 WPF 中,如何在 ItemsControl 模板中正确绑定按钮的样式并使用转换器?
In WPF how do I properly bind the style of a button within an ItemsControl template and use a converter?
在 WPF 中,我试图将按钮创建为 ItemsControl select 中 ItemTemplate 的一部分,使用 class 中的 属性 样式。我以为我的编码是正确的,但是当我 运行 这个时,它创建了按钮 "Test",但它甚至从来没有 运行 样式的转换器。
顺便说一下,是的,我显然知道我还没有正确实现 IValueConverter,但是当我设置断点时,它甚至从未进入转换器。
此外,当 属性 CurrentItemProperty 的值发生变化时,如何正确地保持按钮的样式更新?
MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ButtonStyleConverter x:Key="ButtonStyleConverter"/>
</Window.Resources>
<Grid>
<ItemsControl x:Name="ButtonList">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="OptionButton">
<Button Content="{Binding DisplayName}" Style="{Binding CurrentItem, Converter={StaticResource ButtonStyleConverter}}"></Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfApp1
{
public partial class MainWindow : Window
{
DependencyProperty CurrentItemProperty = DependencyProperty.Register("CurrentItemProperty", typeof(string), typeof(MainWindow));
public string CurrentItem
{
get
{
return (string)GetValue(CurrentItemProperty);
}
set
{
SetValue(CurrentItemProperty, value);
}
}
public MainWindow()
{
InitializeComponent();
ButtonList.ItemsSource = new OptionButton[]
{
new OptionButton() { DisplayName = "Test"}
};
CurrentItem = "Test";
}
public class OptionButton
{
public string DisplayName { get; set; }
}
}
public class ButtonStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
when I set breakpoints, it never even enters the converter.
因为没有什么可转换的。
如果您 运行 调试器中的代码并查看调试输出,您会发现遇到绑定错误,绑定引擎无法找到 属性 CurrentItem
在源对象上。那是因为源对象是一个 OptionButton
实例,它当然没有 CurrentItem
属性.
您有多种选择:
- 以其他方式控制样式。您的问题中没有足够的上下文来了解您为什么要尝试使用转换器来 return 一种样式,但这种方法很不寻常,我建议您应该首先尝试这种方法。可能有比以这种方式使用转换器更好的方法来控制按钮的样式。
- 使用
OptionButton
类型的 属性。在您的示例中,CurrentItem
和 OptionButton.DisplayName
具有相同的值,因此从字面上看示例您可以只绑定到 DisplayName
属性。或者,也许您可以在 OptionButton
中实现一个 属性,委托给您关心的父级值。
- 将绑定源设置为 window,以便
CurrentItem
属性 可见。这个主题有(至少)两个变体:给 window 一个名称属性,并在绑定中按名称引用它,或者只使用 {RelativeSource AncestorType=Window}
标记作为绑定的来源。
最重要的是绑定没有按预期工作,因为绑定的当前数据上下文(定义绑定的默认源)没有您正在绑定的 属性到.
在 WPF 中,我试图将按钮创建为 ItemsControl select 中 ItemTemplate 的一部分,使用 class 中的 属性 样式。我以为我的编码是正确的,但是当我 运行 这个时,它创建了按钮 "Test",但它甚至从来没有 运行 样式的转换器。
顺便说一下,是的,我显然知道我还没有正确实现 IValueConverter,但是当我设置断点时,它甚至从未进入转换器。
此外,当 属性 CurrentItemProperty 的值发生变化时,如何正确地保持按钮的样式更新?
MainWindow.xaml
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ButtonStyleConverter x:Key="ButtonStyleConverter"/>
</Window.Resources>
<Grid>
<ItemsControl x:Name="ButtonList">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="OptionButton">
<Button Content="{Binding DisplayName}" Style="{Binding CurrentItem, Converter={StaticResource ButtonStyleConverter}}"></Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
MainWindow.xaml.cs
namespace WpfApp1
{
public partial class MainWindow : Window
{
DependencyProperty CurrentItemProperty = DependencyProperty.Register("CurrentItemProperty", typeof(string), typeof(MainWindow));
public string CurrentItem
{
get
{
return (string)GetValue(CurrentItemProperty);
}
set
{
SetValue(CurrentItemProperty, value);
}
}
public MainWindow()
{
InitializeComponent();
ButtonList.ItemsSource = new OptionButton[]
{
new OptionButton() { DisplayName = "Test"}
};
CurrentItem = "Test";
}
public class OptionButton
{
public string DisplayName { get; set; }
}
}
public class ButtonStyleConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
when I set breakpoints, it never even enters the converter.
因为没有什么可转换的。
如果您 运行 调试器中的代码并查看调试输出,您会发现遇到绑定错误,绑定引擎无法找到 属性 CurrentItem
在源对象上。那是因为源对象是一个 OptionButton
实例,它当然没有 CurrentItem
属性.
您有多种选择:
- 以其他方式控制样式。您的问题中没有足够的上下文来了解您为什么要尝试使用转换器来 return 一种样式,但这种方法很不寻常,我建议您应该首先尝试这种方法。可能有比以这种方式使用转换器更好的方法来控制按钮的样式。
- 使用
OptionButton
类型的 属性。在您的示例中,CurrentItem
和OptionButton.DisplayName
具有相同的值,因此从字面上看示例您可以只绑定到DisplayName
属性。或者,也许您可以在OptionButton
中实现一个 属性,委托给您关心的父级值。 - 将绑定源设置为 window,以便
CurrentItem
属性 可见。这个主题有(至少)两个变体:给 window 一个名称属性,并在绑定中按名称引用它,或者只使用{RelativeSource AncestorType=Window}
标记作为绑定的来源。
最重要的是绑定没有按预期工作,因为绑定的当前数据上下文(定义绑定的默认源)没有您正在绑定的 属性到.