C# 在WPF中,在用户控件上创建可绑定属性的正确方法是什么?

C# 在WPF中,在用户控件上创建可绑定属性的正确方法是什么?,c#,wpf,xaml,mvvm,data-binding,C#,Wpf,Xaml,Mvvm,Data Binding,这是问题的后续行动。 我为一个控件开发了一个简单的界面,它应该允许用户以最简单的方式定义颜色——通过控制颜色本身的ARGB通道 我希望此控件能够直接绑定到颜色属性,以便允许用户通过滑块进行调整 我遇到了麻烦——我试图用它实现MVVM,但没有成功,因为这样做完全无法从控件中提取控件本身定义的颜色属性 事实上,我甚至不认为这是正确的做法。我需要有几个控件,允许用户更改应用程序的行为和外观,但我不知道如何让UserControl绑定到应用程序的设置(我已经能够绑定单个简单的控件,但是当涉及到像这样的

这是问题的后续行动。 我为一个控件开发了一个简单的界面,它应该允许用户以最简单的方式定义颜色——通过控制颜色本身的ARGB通道

我希望此控件能够直接绑定到颜色属性,以便允许用户通过滑块进行调整

我遇到了麻烦——我试图用它实现MVVM,但没有成功,因为这样做完全无法从控件中提取控件本身定义的颜色属性

事实上,我甚至不认为这是正确的做法。我需要有几个控件,允许用户更改应用程序的行为和外观,但我不知道如何让UserControl绑定到应用程序的设置(我已经能够绑定单个简单的控件,但是当涉及到像这样的复合控件时,我没有得到任何好处)

这是控件本身和MVVM的代码:

public partial class ColorDefiner : UserControl {

    public static readonly DependencyProperty
        _Color = DependencyProperty.Register( "Color", typeof( Color ), typeof( ColorDefiner ) );

    public Color Color {
        get { return ( Color )this.GetValue( ColorDefiner._Color ); }
        set { this.SetValue( ColorDefiner._Color, value ); }
    }

    public ColorDefiner( ) { InitializeComponent( ); }
}


public class ColorViewModel : INotifyPropertyChanged {

    public event PropertyChangedEventHandler PropertyChanged;

    private Color _Color = Colors.Black;

    public double A {
        get { return this.Color.ScA; }
        set {
            this._Color.ScA = ( float )value;
            if ( this.PropertyChanged != null ) {
                this.PropertyChanged( this, new PropertyChangedEventArgs( "A" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
            }
        }
    }
    public double R {
        get { return this.Color.ScR; }
        set {
            this._Color.ScR = ( float )value;
            if ( this.PropertyChanged != null ) {
                this.PropertyChanged( this, new PropertyChangedEventArgs( "R" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Red" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
            }
        }
    }
    public double G {
        get { return this.Color.ScG; }
        set {
            this._Color.ScG = ( float )value;
            if ( this.PropertyChanged != null ) {
                this.PropertyChanged( this, new PropertyChangedEventArgs( "G" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Green" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
            }
        }
    }
    public double B {
        get { return this._Color.ScB; }
        set {
            this._Color.ScB = ( float )value;
            if ( this.PropertyChanged != null ) {
                this.PropertyChanged( this, new PropertyChangedEventArgs( "B" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Blue" ) );
                this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
            }
        }
    }

    public Color Color {
        get { return this._Color; }
        set {
            this._Color = value;
            if ( this.PropertyChanged != null )
                this.AllChanged( );
        }
    }
    public Color Red { get { return Color.FromScRgb( 1.0F, ( float )this.R, 0.0F, 0.0F ); } }
    public Color Green { get { return Color.FromScRgb( 1.0F, 0.0F, ( float )this.G, 0.0F ); } }
    public Color Blue { get { return Color.FromScRgb( 1.0F, 0.0F, 0.0F, ( float )this.B ); } }

    private void AllChanged( ) {
        this.PropertyChanged( this, new PropertyChangedEventArgs( "A" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "R" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "G" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "B" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "Red" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "Green" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "Blue" ) );
        this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
    }
}
我已经尝试在代码中将颜色依赖属性绑定到颜色视图模型;我已经尝试通过XAML中的样式设置器绑定它:

<UserControl.Resources>
    <Style TargetType="Controls:ColorDefiner">
        <Setter Property="Color" Value="{Binding Color, Mode=TwoWay}"/>
    </Style>
</UserControl.Resources>


什么都不管用-什么是合适的方法?(或最佳方法,或最合适的方法,或最普遍接受的实践?)如何从附加到控件的颜色视图模型中提取定义的颜色属性?这样做是否正确?

创建
Color
UserColorSelected
属性:

public Color UserColorSelected
{
   get { return userColorSelected;}
   set{
         userColorSelected=value;                           
         this.PropertyChanged(this, new PropertyChangedEventArgs("UserControlSelected"));

       }
以及每个ARGB属性,设置
UserColorSelected
实例

 public int A
    {
        get
        {

            return a;
        }
        set
        {
            a = value;
            this.UserColorSelected = Color.FromArgb(value, this.R, this.G, this.B);
            this.PropertyChanged(this, new PropertyChangedEventArgs("A"));

        }
    }

请执行,与属性R、G和B类似。

当颜色属性发生更改时,ColorDefiner控件不会做出反应。它应该使用依赖项属性元数据注册PropertyChangedCallback。属性元数据还可以用于指定默认情况下属性是双向绑定的。您还应该遵循WPF中的命名约定,并将DependencyProperty字段命名为
ColorProperty

public partial class ColorDefiner : UserControl
{
    public static readonly DependencyProperty ColorProperty =
        DependencyProperty.Register(
            "Color", typeof(Color), typeof(ColorDefiner),
            new FrameworkPropertyMetadata(
                Colors.Black,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                (o, e) => ((ColorDefiner)o).ColorPropertyChanged((Color)e.NewValue)));

    public Color Color
    {
        get { return (Color)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }

    public ColorDefiner()
    {
        InitializeComponent();
    }

    private void ColorPropertyChanged(Color color)
    {
        sliderA.Value = (double)color.A;
        sliderR.Value = (double)color.R;
        sliderG.Value = (double)color.G;
        sliderB.Value = (double)color.B;
    }

    private void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        Color = Color.FromArgb((byte)sliderA.Value,
            (byte)sliderR.Value, (byte)sliderG.Value, (byte)sliderB.Value);
    }
}
此简单示例显示控件的工作原理:

<Grid>
    <Grid.Background>
        <SolidColorBrush x:Name="brush" Color="AliceBlue"/>
    </Grid.Background>
    <local:ColorDefiner Color="{Binding Color, ElementName=brush}"/>
</Grid>


它可以类似地绑定到任何具有
Color
属性的视图模型。

如何知道VM Color属性没有更新视图的Color属性?如果您已经绑定了属性,那么DP的SetValue()将在内部调用,而不是类上的setter.Damnit,其他将调用!你让我们看起来很糟糕。如果要使用DependencyProperty,必须正确使用它_颜色不对。此外,您对路径在绑定中如何工作的理解是不正确的。它基于DataContext的当前值,而不是当前实例。您必须通过指定和x:Name和Binding.ElementName,或者通过使用FindAncestor的相对资源x:Type UserControl,重新设置到UserControl根目录的路径的基础。哦,好吧。至少你没有为你的UserControl创建ViewModel,所以你已经做到了。你能简单地解释一下我将如何将这个控件的Color属性绑定到应用程序的用户设置中的一个类似属性吗?你是否搜索过StackOverflow(或web)以了解如何绑定到设置属性?答案很多。
<Grid>
    <Grid.Background>
        <SolidColorBrush x:Name="brush" Color="AliceBlue"/>
    </Grid.Background>
    <local:ColorDefiner Color="{Binding Color, ElementName=brush}"/>
</Grid>