带有依赖属性和子控件的用户控件

本文关键字:控件 用户 依赖 属性 | 更新日期: 2023-09-27 18:18:07

我试图在WPF中创建我自己的,非常简单的Usercontrol。它基本上只是一个组合框,里面有一些额外的逻辑。我尝试使用本教程创建自己的依赖属性:http://www.codeproject.com/Articles/140620/WPF-Tutorial-Dependency-Property

到目前为止,这工作得很好,但如果属性发生变化,我也想在用户控件中的组合框上反映这一点。似乎我不能直接将子控件绑定到我的新Dependency-Project。

我的代码现在看起来是这样的:

public partial class ClassSelector : UserControl
{
    public static readonly DependencyProperty CurrentValueProperty =
 DependencyProperty.Register("CurrentValue", typeof(ClassType),
 typeof(ClassSelector), new FrameworkPropertyMetadata());
    public ClassType CurrentValue
    {
        get
        {
            return  (ClassType)this.GetValue(CurrentValueProperty);
        }
        set
        {
            this.SetValue(CurrentValueProperty, value);
        }
    }
    public ClassSelector()
    {
        this.DataContext = this;
        InitializeComponent();
        cmbClassType.ItemsSource = Enum.GetValues(typeof(ClassType));
    }
}

设置依赖属性或组合框的值对我来说似乎很奇怪。我尝试通过:

在xaml中直接绑定它
<Grid>
    <ComboBox x:Name="cmbClassType" SelectedItem="{Binding Path=CurrentValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="cmbClassType_SelectionChanged" />
</Grid>

我尝试将dependency - project changed Event映射到组合框,反之亦然,但是这会导致非常奇怪的代码,因为组合框的更改必须更改组合框的属性值和属性值。

我很确定有可能绑定一个DependencyProperty到子控件,但我找不到一种方法来使这个工作。

提前感谢大家的建议,祝周末愉快

马提亚

Edith说:调用窗口需要将对象绑定到网格上,而不是绑定到窗口上,所以例如:

grdMain.DataContext = new DeckSearch();

工作正常,同时

this.DataContext = new DeckSearch();

此行为仅在我的自定义控件,所有其他控件与窗口本身的DataContext一起工作得很好。

带有依赖属性和子控件的用户控件

好了,这里我修复了你的代码,它在我的末端工作了

UserControlCodeBehind

public partial class ClassSelector : UserControl
{
    public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register("CurrentValue", typeof(ClassType),
        typeof(ClassSelector), new FrameworkPropertyMetadata()
            {
                DefaultValue = ClassType.Type1,
                BindsTwoWayByDefault = true,
                PropertyChangedCallback = CurrentValueChanged,
                DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
            });

    private static void CurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var obj = (ClassSelector)d;
        obj.cmbClassType.SelectedValue = e.NewValue;
    }
    public ClassType CurrentValue
    {
        get
        {
            return (ClassType)this.GetValue(CurrentValueProperty);
        }
        set
        {
            this.SetValue(CurrentValueProperty, value);
        }
    }
    public ClassSelector()
    {
        InitializeComponent();
        cmbClassType.ItemsSource = Enum.GetValues(typeof(ClassType));
        cmbClassType.SelectedValue = CurrentValue;
    }
}

UserControl的Xaml部分

<Grid>
    <ComboBox x:Name="cmbClassType" SelectedValue="{Binding Path=CurrentValue}"/>
</Grid>

请检查您的终端是否正常工作。我没有添加任何额外的代码检查线程安全性和所有。

编辑

在我的解决方案中,当CurrentValue变化时,我确实得到了Class Property通知。

下面是我的示例MainWindow代码。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        Task.Run(() =>
            {
                Thread.Sleep(1000);
                Dispatcher.InvokeAsync(() =>
                    {
                        customCombobox.CurrentValue = ClassType.Type3;//Updating the UserControl DP
                    });
                Thread.Sleep(2000);
                this.CurrentValue = ClassType.Type2;//Updating my local Property
            });
    }
    private ClassType _currentValue;
    public ClassType CurrentValue
    {
        get { return _currentValue; }
        set
        {
            _currentValue = value;
            Debug.WriteLine("Value Changed to " + value.ToString());
            RaisePropertyChanged("CurrentValue");
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
    void RaisePropertyChanged(string propName)
    {
        var pc = PropertyChanged;
        if (pc != null)
            pc(this, new PropertyChangedEventArgs(propName));
    }
}

和mainwindow。xaml

<Window x:Class="WpfApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication"
    Title="MainWindow" Height="250" Width="525">
<local:ClassSelector x:Name="customCombobox" Height="25" CurrentValue="{Binding CurrentValue}"/>
</Window>