【问题标题】:Binding WPF Extended Toolkit ColorPicker SelectedColor Property to DependencyProperty将 WPF 扩展工具包 ColorPicker SelectedColor 属性绑定到 DependencyProperty
【发布时间】:2018-08-14 17:54:02
【问题描述】:

我正在尝试将 WPF Extended Toolkit ColorPicker 的 SelectedColor 属性绑定到类型为 SolidColorBrushDependencyProperty。然后,该颜色应该用作画布上/画布中的形状的填充颜色。

这不起作用,据我了解,问题在于 ColorPicker 的 SelectedColor 属性实际上是一个类型为 Color? 的对象。我的问题是,我该如何让它工作?如果我只是通过与事件挂钩的方法在代码中执行此操作,我可以使用SelectedColor.Value,但 AFAIK 不是 XAML 中的选项。

我确实尝试使用常规属性并让类继承自 INotifyPropertyChanged(如 SelectedColor binding doesn't update from ColorPicker to Model),而不是从 DependencyObject,但这也不起作用。

我更喜欢用 Binding 来做这件事,因为我试图在使用 MVVM 的实践中获得更多。我最近才学会如何使用 MVVM,而且我现在更喜欢它,所以我真的很想避免只使用代码隐藏。

XAML:

    <toolkit:ColorPicker x:Name="fillColor" Grid.Column="1" Grid.Row="8" Margin="5" VerticalAlignment="Top" SelectedColor="{Binding Path=FillColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedColorChanged="fillColor_SelectedColorChanged" />
    <toolkit:ColorPicker x:Name="lineColor" Grid.Column="2" Grid.Row="8" Margin="5" VerticalAlignment="Top" />

C#: 私有静态 DependencyProperty FillColorProperty = DependencyProperty.Register("FillColor", typeof(SolidColorBrush), typeof(TuckboxModel), new FrameworkPropertyMetadata(Brushes.Purple));

    private static DependencyProperty LineColorProperty = DependencyProperty.Register("LineColor", typeof(SolidColorBrush),
        typeof(TuckboxModel), new FrameworkPropertyMetadata(Brushes.Black));

public SolidColorBrush FillColor
    {
        get { return (SolidColorBrush)GetValue(FillColorProperty); }
        set
        {
            SetValue(FillColorProperty, value);
        }
    }

    public SolidColorBrush LineColor
    {
        get { return (SolidColorBrush)GetValue(LineColorProperty); }
        set { SetValue(LineColorProperty, value); }
    }

public void CreateBox(Canvas drawingCanvas, TuckboxModel model, double width, double height, double depth, SolidColorBrush shading, SolidColorBrush outline)
    {
        double xOrigin = 50;
        double yOrigin = 450;

        double xCoord = xOrigin;
        double yCoord = yOrigin;
        Shape item;
        double flapSize;
        long count;

        //Remove all previous shapes from Canvas
        drawingCanvas.Children.Clear();

        Path border = new Path();
        border.Stroke = model.LineColor;
        border.StrokeThickness = 1.0;            
        border.Fill = model.FillColor;
        //border.Fill = shading;

        yCoord -= ToPts(depth);
        xCoord += ToPts(depth);

        RectangleGeometry rectangleA = new RectangleGeometry();
        Rect rectA = new Rect(xCoord, yCoord, ToPts(width), ToPts(depth));
        rectangleA.Rect = rectA;

        xCoord += ToPts(width);

        RectangleGeometry rectangleB = new RectangleGeometry();
        Rect rectB = new Rect(xCoord + 3, yCoord, ToPts(depth) - 5, ToPts(depth));
        rectangleB.Rect = rectB;

        xCoord += ToPts(depth);

        RectangleGeometry rectangleC = new RectangleGeometry();
        Rect rectC = new Rect(xCoord + 2, yCoord, ToPts(width) - 4, ToPts(depth) - 2);
        rectangleC.Rect = rectC;

        xCoord += ToPts(width);

        RectangleGeometry rectangleD = new RectangleGeometry();
        Rect rectD = new Rect(xCoord + 2, yCoord, ToPts(depth) - 5, ToPts(depth));
        rectangleD.Rect = rectD;

        xCoord = xOrigin;
        yCoord -= ToPts(height);

        RectangleGeometry rectangleE = new RectangleGeometry();
        Rect rectE = new Rect(xCoord, yCoord, ToPts(depth), ToPts(height));
        rectangleE.Rect = rectE;

        xCoord += ToPts(depth);

        RectangleGeometry rectangleF = new RectangleGeometry();
        Rect rectF = new Rect(xCoord, yCoord, ToPts(width), ToPts(height));
        rectangleF.Rect = rectF;

        xCoord += ToPts(width);

        RectangleGeometry rectangleG = new RectangleGeometry();
        Rect rectG = new Rect(xCoord, yCoord, ToPts(depth), ToPts(height));
        rectangleG.Rect = rectG;

        xCoord += ToPts(depth);

        RectangleGeometry rectangleH = new RectangleGeometry();
        Rect rectH = new Rect(xCoord, yCoord, ToPts(width), ToPts(height));
        rectangleH.Rect = rectH;

        xCoord += ToPts(width);

        RectangleGeometry rectangleI = new RectangleGeometry();
        Rect rectI = new Rect(xCoord, yCoord, ToPts(depth) - 3, ToPts(height));
        rectangleI.Rect = rectI;

        xCoord = xOrigin;
        yCoord -= ToPts(depth);

        RectangleGeometry rectangleJ = new RectangleGeometry();
        Rect rectJ = new Rect(xCoord + 1, yCoord, ToPts(depth) - 2, ToPts(depth));
        rectangleJ.Rect = rectJ;

        xCoord += ToPts(depth);

        RectangleGeometry rectangleK = new RectangleGeometry();
        Rect rectK = new Rect(xCoord, yCoord, ToPts(width), ToPts(depth));
        rectangleK.Rect = rectK;

        xCoord += ToPts(width);

        RectangleGeometry rectangleL = new RectangleGeometry();
        Rect rectL = new Rect(xCoord + 1, yCoord, ToPts(depth) - 2, ToPts(depth));
        rectangleL.Rect = rectL;            

        EllipseGeometry ellipseA = new EllipseGeometry();
        ellipseA.Center = new Point(rectK.Right - (rectK.Width / 2), yCoord);
        ellipseA.RadiusX = rectK.Width / 2;

        if(height < 1.0)
            flapSize = ToPts(height);
        else
            flapSize = 72;

        ellipseA.RadiusY = flapSize;

        GeometryGroup finalShape = new GeometryGroup();
        finalShape.Children.Add(rectangleA);
        finalShape.Children.Add(rectangleB);
        finalShape.Children.Add(rectangleC);
        finalShape.Children.Add(rectangleD);
        finalShape.Children.Add(rectangleE);
        finalShape.Children.Add(rectangleF);
        finalShape.Children.Add(rectangleG);

        finalShape.Children.Add(rectangleH);
        finalShape.Children.Add(rectangleI);
        finalShape.Children.Add(rectangleJ);
        finalShape.Children.Add(rectangleK);
        finalShape.Children.Add(rectangleL);
        finalShape.Children.Add(ellipseA);

        finalShape.FillRule = FillRule.Nonzero;

        border.Data = finalShape;

        drawingCanvas.Children.Add(border);
    }

任何帮助将不胜感激!

【问题讨论】:

    标签: c# wpf mvvm dependency-properties wpf-extended-toolkit


    【解决方案1】:

    我认为Converter 可以解决您的问题。下面是一个转换器类的例子:

    using System;
    using System.Globalization;
    using System.Windows.Data;
    
    namespace SO_app.Converters
    {
        public class DebugConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                if (null == value) {
                    return null;
                }
                // For a more sophisticated converter, check also the targetType and react accordingly..
                if (value is Color) {
                    Color color = (Color)value;
                    return new SolidColorBrush(color);
                }
                // You can support here more source types if you wish
                // For the example I throw an exception
    
                Type type = value.GetType();
                throw new InvalidOperationException("Unsupported type ["+type.Name+"]");  
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
        }
    }  
    

    然后在您的 xaml 中它看起来像这样:
    这是我的项目:

    xmlns:converter="clr-namespace:SO_app.Converters"
    

    然后在资源中:

    <converter:DebugConverter x:Key="DebugConverter"/>
    

    然后在 xaml 中:

    <toolkit:ColorPicker x:Name="fillColor" Grid.Column="1" Grid.Row="8" Margin="5" VerticalAlignment="Top" SelectedColor="{Binding Path=FillColor, Converter={StaticResource DebugConverter}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedColorChanged="fillColor_SelectedColorChanged" />  
    

    注意:
    类型转换的代码来自这个SO post
    更新:
    检查this SO post,表示工具包中有内置转换器

    【讨论】:

    • 我没有想到,但应该有。我认为这绝对是答案,尽管由于不同的原因它实际上不适用于我的情况。当我动态生成形状时(并且需要,因为整个应用程序是基于输入尺寸的形状生成器),没有地方可以将绑定绑定到转换器。当我将绑定放在 ColorPicker SelectedColor 属性中时,它会触发 ConvertBack 方法。这是由于 Converter 绑定的“向后”性质(至少在我看来是向后的),您在控件中绑定到您想要更改的控件。
    • 您可以有一个SelectedShape 属性,这将允许您将其设置为当前选择的颜色。
    • SelectedShape 会进入哪个对象?喜欢动态形状?我对这种方法很感兴趣,因为我宁愿使用绑定,但我并没有准确地想象它会是什么样子。
    猜你喜欢
    • 2012-11-16
    • 2012-11-12
    • 1970-01-01
    • 1970-01-01
    • 2019-09-07
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多