WPF UserControl 无法与 DependencyProperty OnSomeBytePropertyChanged 一起使用

问题描述 投票:0回答:1

首先,我在

UserControl
项目中制作了一个
WPF
,用于在设置窗口中设置颜色。

Window 有一个名为

MainWindowViewModel.cs
的 ViewModel,其中包含:

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Windows.Media;

namespace integrate.vsto.planning.settings.wpf.Viewmodels
{
    /// <summary>
    /// The Viewmodel used in the MainWindow
    /// </summary>
    public class MainWindowViewModel : INotifyPropertyChanged
    {

        #region Fields (Border color)

        /// <summary>
        /// Red value (0-255) of the border color
        /// </summary>
        private byte _borderColorR { get; set; } = 200;

        /// <summary>
        /// Green value (0-255) of the border color
        /// </summary>
        private byte _borderColorG { get; set; } = 200;

        /// <summary>
        /// Blue value (0-255) of the border color
        /// </summary>
        private byte _borderColorB { get; set; } = 200;

        #endregion

        #region Properties (Border color)

        /// <summary>
        /// Red value (0-255) of the border color
        /// </summary>
        public byte BorderColorR
        {
            get { return _borderColorR; }
            set
            {
                _borderColorR = value;
                OnPropertyChanged(nameof(BorderColorR));
                OnPropertyChanged(nameof(BorderColorBrush));
            }
        }

        /// <summary>
        /// Green value (0-255) of the border color
        /// </summary>
        public byte BorderColorG
        {
            get { return _borderColorG; }
            set
            {
                _borderColorG = value;
                OnPropertyChanged(nameof(BorderColorG));
                OnPropertyChanged(nameof(BorderColorBrush));
            }
        }

        /// <summary>
        /// Blue value (0-255) of the border color
        /// </summary>
        public byte BorderColorB
        {
            get { return _borderColorB; }
            set
            {
                _borderColorB = value;
                OnPropertyChanged(nameof(BorderColorB));
                OnPropertyChanged(nameof(BorderColorBrush));
            }
        }

        /// <summary>
        /// WPF compatible color for any element containing an implementation for a Brush
        /// </summary>
        public Brush BorderColorBrush
        {
            get
            {
                return new SolidColorBrush(Color.FromRgb(BorderColorR, BorderColorG, BorderColorB));
            }
        }

        #endregion

        #region Events

        /// <summary>
        /// The event triggered on any Property changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Fires the PropertyChanged event for the given property (by name)
        /// </summary>
        /// <param name="propertyName">Given property name</param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

    }
}

此视图模型包含的内容比给定的代码多得多,并且对于不包含用户控件交互的所有内容都可以正常工作,例如普通文本框中呈现的文本和其他字节。所以我的 MainWindow 和 Viewmodel 之间的链接已正确设置,如

this.DataContext = new MainWindowViewModel();

然后是名为

ColorSettingUserControl

的 UserControl
using integrate.vsto.planning.settings.wpf.Viewmodels;
using System.Windows;
using System.Windows.Controls;

namespace integrate.vsto.planning.settings.wpf
{
    /// <summary>
    /// Interaction logic for ColorSettingUserControl.xaml
    /// </summary>
    public partial class ColorSettingUserControl : UserControl
    {
        /// <summary>
        /// The viewmodel for the color settings user control
        /// </summary>
        private ColorSettingViewModel _viewmodel;
    
        #region Attribute Registry

        /// <summary>
        /// The red value (0-255) for the preview control
        /// </summary>
        public static readonly DependencyProperty RedProperty =
            DependencyProperty.Register(nameof(Red), typeof(byte), typeof(ColorSettingUserControl), new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnRedPropertyChanged))

        /// <summary>
        /// The green value (0-255) for the preview control
        /// </summary>
        public static readonly DependencyProperty GreenProperty =
            DependencyProperty.Register(nameof(Green), typeof(byte), typeof(ColorSettingUserControl), new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnGreenPropertyChanged))

        /// <summary>
        /// The blue value (0-255) for the preview control
        /// </summary>
        public static readonly DependencyProperty BlueProperty =
            DependencyProperty.Register(nameof(Blue), typeof(byte), typeof(ColorSettingUserControl), new FrameworkPropertyMetadata((byte)0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnBluePropertyChanged))

        #endregion

        #region Attribute Properties

        /// <summary>
        /// Color value red (0-255)
        /// </summary>
        public byte Red
        {
            get { return (byte)GetValue(RedProperty); }
            set { _viewmodel.Red = value; SetValue(RedProperty, value); }
        }

        /// <summary>
        /// Color value green (0-255)
        /// </summary>
        public byte Green
        {
            get { return (byte)GetValue(GreenProperty); }
            set { _viewmodel.Green = value; SetValue(GreenProperty, value); }
        }

        /// <summary>
        /// Color value blue (0-255)
        /// </summary>
        public byte Blue
        {
            get { return (byte)GetValue(BlueProperty); }
            set { _viewmodel.Blue = value; SetValue(BlueProperty, value); }
        }

        #endregion

    }
}

最后,这是我需要工作的 UserControl 中的 XAML 行:

<UserControl x:Class="integrate.vsto.planning.settings.wpf.ColorSettingControl"
    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" 
    xmlns:local="clr-namespace:integrate.vsto.planning.settings.wpf"
    mc:Ignorable="d" 
    d:DesignHeight="100" d:DesignWidth="800">

    <TextBox x:Name="txt_R" Text="{Binding Rood}" Width="46" />
    <TextBox x:Name="txt_G" Text="{Binding Green}" Width="46" />
    <TextBox x:Name="txt_B" Text="{Binding Blue}" Width="46" />

</UserControl>

然后是 MainWindow 实现 UserControl 的 XAML

<local:ColorSettingUserControl
    Red="{Binding BorderColorR}" 
    Green="{Binding BorderColorG}" 
    Blue="{Binding BorderColorB}" />

所以我没有将

BorderColorR
的实际值从主窗口的视图模型获取到用户的控件文本框中。调试时,调试器也不会停止在公共字节红色的设置器中,也不会停止在绿色或蓝色的设置器中。

不确定我需要朝哪个方向进行研究才能使这项工作成功。

我尝试了什么

我尝试在

PropertyMetadata
中使用
FrameworkPropertyMetadata
而不是
ColorSettingUserControl.cs
作为依赖属性。

当尝试不带 Binding 的值时,如

<ColorSettingUserControl Red="20" />
,它实际上会触发 DependencyProperty 的 setter。

我所期待的

我希望

<ColorSettingUserControl Red={Binding BorderColorR} />
触发 DependencyProperty 的 setter,它在其私有声明中具有默认值。

c# wpf xaml mvvm dependency-properties
1个回答
0
投票

您在

UserControl
内的绑定是错误的。他们使用
DataContext
作为数据源,这是错误的。他们必须使用
UserControl
作为数据源。

您可以通过使用

Bindig.RelativeSource
(或者性能更好的
Binding.ElementName
)来实现此目的:

<UserControl x:Name="Root">

  <!-- Option #1: Use Bindig.RelativeSource -->
    <TextBox x:Name="txt_R" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Red}" Width="46" />

  <!-- Option #2: Use Binding.ElementName -->
    <TextBox x:Name="txt_G" Text="{Binding ElementName=Root, Path=Green}" Width="46" />

    <TextBox x:Name="txt_B" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=Blue}" Width="46" />
</UserControl>
© www.soinside.com 2019 - 2024. All rights reserved.