综合编程

TwoWay Binding on WPF UserControl

微信扫一扫,分享到朋友圈

TwoWay Binding on WPF UserControl
0

I’m trying to build a simple Color Picker as a WPF UserControl, but I’m having trouble getting the selected color back to the main window.

My main window XAML looks like this:

<Window x:Class="ColorPicker.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:view="clr-namespace:ColorPicker"
        Title="TestWindow" SizeToContent="WidthAndHeight">
    <StackPanel Orientation="Horizontal">
        <Rectangle Fill="{Binding MyColor}" Margin="10,10,10,10" Width="100" Height="300"/>
        <view:WPFColorPicker SelectedColor="{Binding MyColor, Mode=TwoWay}" Width="200" Height="300"/>
    </StackPanel>
</Window>

and the view model and code-behind:

namespace ColorPicker
{
    public class TestViewModel
    {
        public TestViewModel()
        {
            MyColor = new SolidColorBrush(Color.FromRgb(255, 0, 0));
        }

        public Brush MyColor { get; set; }
    }

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new TestViewModel();
        }
    }
}

The WPFColorPicker usercontrol XAML is:

<UserControl x:Class="ColorPicker.WPFColorPicker"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Rectangle x:Name="rtlfill" Fill="{Binding SelectedColor}" HorizontalAlignment="Stretch" Height="60" Margin="10,10,10,10" Stroke="Black" VerticalAlignment="Top"/>
        <ListBox HorizontalAlignment="Stretch" SelectedValue="{Binding SelectedColor}" VerticalAlignment="Stretch" Margin="0,0,0,81" ScrollViewer.HorizontalScrollBarVisibility="Disabled" x:Name="colorList">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel IsItemsHost="True" Orientation="Horizontal"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Rectangle Fill="{Binding .}" Margin="0,0,0,5" Width="20" Height="20" Stroke="#FF211E1E" OpacityMask="Black" StrokeThickness="1" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</UserControl>

and code-behind:

namespace ColorPicker
{
    public partial class WPFColorPicker : UserControl
    {
        List<Brush> brushList;

        public WPFColorPicker()
        {
            InitializeComponent();

            brushList = new List<Brush>() {
                new SolidColorBrush(Color.FromRgb(255,  0,  0)),
                new SolidColorBrush(Color.FromRgb(  0,255,  0)),
                new SolidColorBrush(Color.FromRgb(  0,  0,255))};

            this.colorList.ItemsSource = brushList;
            DataContext = this;
        }

        public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor",
            typeof(Brush),
            typeof(WPFColorPicker),
            new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Red),
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public Brush SelectedColor
        {
            get { return (Brush)GetValue(SelectedColorProperty); }
            set { SetValue(SelectedColorProperty, value); }
        }
    }
}

So, the problem I’m having is that binding on SelectedColor (using MyColor from TestViewModel) doesn’t work.

From looking at other questions on StackOverflow and various tutorials, I think have the UserControl set up correct to bind SelectedColor as a TwoWay DependencyProperty, but its not working.

Can someone provide me some insight?

Each FrameworkElement
can have only one DataContext
so when you do

DataContext = this;

in UserControl
constructor you overwrite DataContext
normally inherited through visual tree and that affects default binding context for WPFColorPicker
and all children, including

<view:WPFColorPicker SelectedColor="{Binding MyColor, Mode=TwoWay}" .../>

Remove that line from WPFColorPicker
constructor and instead give UserControl
some name

<UserControl x:Class="ColorPicker.WPFColorPicker" ... x:Name="myUserControl">

and change bindings inside UserControl
to use that name

<Rectangle ... Fill="{Binding ElementName=myUserControl, Path=SelectedColor}"/>
<ListBox ... SelectedValue="{Binding ElementName=myUserControl, Path=SelectedColor}">

EDIT

As a side note you need to be aware that Brush
is compared by reference so ListBox.SelectedValue
will not preselect value unless it’s one of instances from the brushList
, which is not possible as you create the list every time. Basically two different instances of SolidColorBrush
, even with the same Color
, are different for equality check

阅读原文...


微信扫一扫,分享到朋友圈

TwoWay Binding on WPF UserControl
0

Hello, buddy!

Dog Breed Classifier — using Convolutional Neural Networks

上一篇

AutoEncoder in Spectrogram

下一篇

评论已经被关闭。

插入图片

热门分类

往期推荐

TwoWay Binding on WPF UserControl

长按储存图像,分享给朋友