In WPF, I am trying to have the button created as part of the ItemTemplate in a ItemsControl select the style using a property within the class. I thought I had it coded correctly, but when I run this, it creates the button "Test", but it never even runs the converter for the Style.
By the way, yes, I'm obviously aware that I haven't properly implemented the IValueConverter yet, but when I set breakpoints, it never even enters the converter.
Also, how do I properly keep the style of the button updated when the value of the property CurrentItemProperty changes?
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.
Because there's nothing to convert.
If you would run your code in the debugger and look at the debug output, you'd find that you're getting a binding error, where the binding engine fails to find the property CurrentItem
on the source object. That's because the source object is a OptionButton
instance, which of course does not have a CurrentItem
property.
You have a number of options available to you:
OptionButton
type. In your example, the CurrentItem
and OptionButton.DisplayName
have the same value, so taking the example literally you could just bind to the DisplayName
property instead. Alternatively, maybe you could implement a property in OptionButton
that delegates to the parent-level value you care about.CurrentItem
property is visible. There are (at least) two variations on this theme: give the window a name attribute, and refer to it by name in the binding, or just use {RelativeSource AncestorType=Window}
markup for the source of the binding.The bottom line is that the binding doesn't work as expected because the current data context for the binding (which defines the default source for the binding) doesn't have the property you're binding to.