I have a problem with button bindings in user control. This thing bugs me for days and I can't seem to get it working right.
The idea is to have several buttons in user control(which can be added dynamically). Every button can have a different title and a different value. Buttons should be able to disable/enable each others, example if "Option 1" is clicked "Option 9" should be disabled. User Control Example
User control is a simple StackPanel with multiple buttons as seen on the image. I've implemented a DependencyProperty as int named Value. When any of the button is clicked, Value is changed by the value of the button. I've binded that Value to model value. When any button is clicked model value changes. But, when I change model value, control value does not change. How to do it two way correctly? How to select only one button which is in the model? I've also tried implementing INotifyPropertyChanged into my user control but it didn't work. I've also tried some other things I've read here, but it didn't work.
In short, I need a group of buttons which have different values and map their own values into one value if clicked. I should be able to get/set that value from my model.
I also need some kind of way to enable/disable buttons depending on which button is clicked. As I wrote already, if button "Option 1" is clicked it should disable "Option 9" button. Any way to do that via data binding? Value converter?
Thnx!
Control
namespace TestApp
{
public partial class SingleOptionControl : UserControl
{
private static SolidColorBrush _selectedColorBrush = new SolidColorBrush(Color.FromRgb(0, 120, 200));
private SingleOptionModel _model;
private List<Button> _buttons;
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(SingleOptionControl), new PropertyMetadata(null));
public SingleOptionControl()
{
InitializeComponent();
_buttons = new List<Button>();
this.DataContext = this;
}
private void buttonIndex_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
ButtonOption option = (ButtonOption)button.Tag;
int index = option.Index;
Console.WriteLine("Current index = {0} | Value = {1}", index, option.Value);
// Update the Value
Value = option.Value;
// Deselect
DeselectButtons();
// Select
SelectButton(index);
}
private void SelectButton(int index)
{
Button button = _buttons[index];
button.Foreground = _selectedColorBrush;
button.FontWeight = FontWeights.Bold;
button.FontSize = 14.0;
}
private void DeselectButtons()
{
foreach (Button button in _buttons)
{
button.Foreground = Brushes.Black;
button.FontWeight = FontWeights.Normal;
button.FontSize = 12.0;
}
}
public void Create(SingleOptionModel model)
{
_model = model;
labelTitle.Content = model.Title;
int index = 0;
List<ButtonSection> sections = model.Sections;
foreach (ButtonSection section in sections)
{
List<ButtonOption> options = section.Options;
foreach (ButtonOption option in options)
{
option.Index = index;
Button button = createButton(option);
button.Click += buttonIndex_Click;
stackPanel1.Children.Add(button);
_buttons.Add(button);
index++;
}
Separator separator = createSeparator();
stackPanel1.Children.Add(separator);
}
labelDefaultValue.Content = model.DefaultOption.Value;
Value = model.DefaultOption.Value;
}
private Button createButton(ButtonOption option)
{
Button button = new Button();
button.FontSize = 12.0;
button.Content = option.Title;
button.Tag = option;
button.Height = 36;
button.MinWidth = 48;
button.Padding = new Thickness(6, 0, 6, 0);
button.Margin = new Thickness(1, 0, 1, 0);
return button;
}
private Separator createSeparator()
{
Separator separator = new Separator();
separator.Width = 6;
separator.Background = null;
return separator;
}
}
}
UserControl
<UserControl x:Class="TestApp.SingleOptionControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="167" d:DesignWidth="800">
<Grid Name="gridMain" Height="96">
<Label Height="30" HorizontalAlignment="Stretch" Name="labelTitle" VerticalAlignment="Top" Background="{x:Null}" VerticalContentAlignment="Center" FontSize="18" FontStyle="Normal" FontWeight="Bold" Padding="10,0,0,0" Margin="0,2,0,0" />
<StackPanel Height="40" HorizontalAlignment="Stretch" Margin="10,32,0,0" Name="stackPanel1" VerticalAlignment="Top" Orientation="Horizontal"></StackPanel>
<Label Content="Default:" Height="28" HorizontalAlignment="Left" Margin="4,68,0,0" Name="label2" VerticalAlignment="Top" Width="50" Padding="10,0,0,0" VerticalContentAlignment="Center" />
<Label Content="Value" Height="28" HorizontalAlignment="Left" Margin="60,68,0,0" Name="labelDefaultValue" VerticalAlignment="Top" Width="384" Padding="0" VerticalContentAlignment="Center" />
<Rectangle Height="1" HorizontalAlignment="Stretch" Name="rectangle1" Stroke="{x:Null}" VerticalAlignment="Top" Fill="#14000000" />
</Grid>
</UserControl>
Class TestModel
namespace TestApp
{
public class TestModel : INotifyPropertyChanged
{
private byte _testValue;
public byte TestValue
{
get { return _testValue; }
set
{
_testValue = value;
OnPropertyChanged("TestValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}