WPF绑定命令到colorpicker

时间:2016-10-10 11:28:22

标签: c# wpf data-binding

首先,在我的应用程序中,我使用Extended WPF Toolkit ColorPicker。

在画布上,我根据反序列化的XML文件绘制了几个矩形(这很有效)。对于每个绘制的矩形,我添加一个ColorPicker,以便应用程序的用户可以更改矩形的颜色。我尝试使用ICommand界面,但颜色选择器似乎不支持绑定自定义命令,所以我有点卡住而且不知道该怎么做。这是我目前的代码:

<ItemsControl Name="inputs2">
      <ItemsControl.ItemTemplate>
      <DataTemplate>
      <Grid Name="testgrid" Margin="0,0,0,5">
      <Grid.ColumnDefinitions>
           <ColumnDefinition Width="*" />
           <ColumnDefinition Width="*" />
           </Grid.ColumnDefinitions>

           <TextBlock HorizontalAlignment="Left" Grid.Column="0" Text="{Binding Title}" />
           <xctk:ColorPicker HorizontalAlignment="Left" 
                             Grid.Column="1" 
                             Name="ClrPcker_Background" 
                             SelectedColor="{Binding Color}" 

                           <!--tryig to bind here???-->
            />
       </Grid>
       </DataTemplate>
       </ItemsControl.ItemTemplate>
</ItemsControl> 

我的C#

internal class BackgroundInput
{
    public BackgroundInput()
    {
    }

    public string Color { get; set; }
    public string Title { get; set; }
}

第二部分:

public override void Draw(Canvas label)
{
    Rectangle rect = new Rectangle();
    //...... drawing method
    label.Children.Add(rect );
}

internal override void AddInputs(ItemsControl inputPanel)
{
    inputPanel.Items.Add(new BackgroundInput() { Title = "Backgroundcolor:", Color = BackgroundColor });        
}
//both methods get called

因此,每当ColorPicker的颜色发生变化时,我都希望连接的矩形更新它的背景颜色。 ColorPicker似乎不支持Command="..."CommandParameter="..."发送数据,因此我想就如何执行此操作提供建议。谢谢!

修改

我现在拥有的一个小例子。如果用户更改颜色选择器的颜色,我会尝试更改颜色。

enter image description here

修改

我有点工作,但我不认为这是正确的方法。这是我的更新代码:

internal class BackgroundInput
{
    private string _bg;
    public BackgroundInput()
    {
    }

    public Box Box { get; internal set; }

    public string Color
    {
        get { return _bg; }
        set { _bg = value; Box.BackgroundColor = _bg; Box.redraw(); }
    }

    public string Title { get; set; }
}

矩形代码:

public class Box : Field
{
      Canvas label;
    Border _border;

    public override void Draw(Canvas label)
    {
        _border = new Border();
        _label = label;
        Rectangle x= new Rectangle ();

        label.Children.Add(x);
    }

    internal override void AddInputs(ItemsControl inputPanel)
    {
        inputPanel.Items.Add(new BackgroundInput() { Title = "Background:", Box = this, Color = BackgroundColor });           
    }   

    public void redraw()
    {
        _label.Children.Remove(_label);
        Draw(_label);
    }
}

1 个答案:

答案 0 :(得分:1)

我强烈建议您使用MVVM模式。我想你有一个想要在布局面板上绘制的对象列表(在这种情况下是画布)。

首先需要的是ViewModel。它将代表一个Rectangle实例:

public class MyRectangleViewModel : INotifyPropertyChanged
{
    private Color _background;
    public Color Background
    {
        get
        {
            return _background;
        }
        set
        {
            _background = value;
            OnPropertyChanged();
        }
    }

    /// <summary>
    /// Occurs when [property changed].
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

请注意INotifiyPropertyChanged界面。这将添加“WPF绑定魔法”。每次更改属性时,都会触发PropertyChanged事件。在SO和网络上有大量的教程和示例......

您可以使用ItemsControl或类似物品,并将所有物品绑定到ItemsSource。

反正。看起来你想在代码中创建所有元素(无论出于何种原因)。所以这里有一个解决方案背后的代码#ItGivesMeTheCreeps:

/// <summary>
/// All my recangles
/// </summary>
private ObservableCollection<MyRectangleViewModel> AllMyRecangles = new ObservableCollection<MyRectangleViewModel>();
/// <summary>
/// Call this method if you add/remove objects to your list.
/// </summary>
public void RefreshObjects()
{
    this.myCanvas.Children.Clear();

    foreach (MyRectangleViewModel item in AllMyRecangles)
    {
        Rectangle newRectangle = new Rectangle();

        //set the DataContext
        newRectangle.DataContext = item;

        //create the binding
        Binding b = new Binding();
        b.Source = item;
        b.Path =new PropertyPath(nameof(Background));
        b.Mode = BindingMode.TwoWay;
        b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;

        //setup the binding XAML: <Rectangle Fill = {Binding Path="Background", Mode=TwoWay, UpdateSourceTrigger ="PropertyChanged" />
        BindingOperations.SetBinding(newRectangle, Rectangle.FillProperty, b);


        //add the rectangle to the canvas
        myCanvas.Children.Add(newRectangle);
    }
}