【问题标题】:WPF: UserControl with Dependency Property and sub-controlsWPF:具有依赖属性和子控件的用户控件
【发布时间】:2014-10-09 13:41:46
【问题描述】:

我正在尝试在 WPF 中创建自己的、非常简单的用户控件。它基本上只是一个组合框,里面有一些额外的逻辑。 我尝试使用本教程创建自己的 Depdency-Property: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>

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

我很确定必须有可能将 DependencyProperty 绑定到子控件,但我找不到实现此功能的方法。

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

马蒂亚斯

Edith说:调用Window需要将Object绑定到Grid,而不是Window,例如:

grdMain.DataContext = new DeckSearch();

同时工作正常

this.DataContext = new DeckSearch();

此行为仅适用于我的自定义控件,所有其他控件都可以与 Window 本身的 DataContext 完美配合。

【问题讨论】:

  • 不要this.DataContext = this。这是有罪、肮脏和错误的,如果你这样做,魔鬼会吃掉你的 Visual Studio。
  • 如果我设置它,Combobox 将绑定到枚举的默认值。如果我删除它,它一直是空的,这更糟。
  • HighCore 的意思是你应该命名Grid,例如使用x:Name="root",并在其上设置DataContextroot.DataContext = this。至于您的问题,我不明白,因为我可以从 ComboBox 中选择一个值,并且它已正确更新。您能否显示更多代码或重现方法?
  • 您好,感谢您的回复,我正在使用 DataContext,但不知道到底发生了什么。我想我将不得不阅读一些关于它的东西,但感谢您的输入。关于控件:您是否尝试在窗口上设置控件并绑定新的“CurrentValue”属性?它一直是空的,但我得到了 DependencyProperty-changed 事件

标签: c# wpf xaml combobox user-controls


【解决方案1】:

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

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>

【讨论】:

  • 非常感谢,这很奇怪:如果我将 Datacontext 设置为 Grid,它就可以工作,如果我将它设置为 Window 本身,它就不行。如前所述,我需要更多地了解 Datacontext 以及为什么会发生这样的事情。
  • 不客气 :)。有时 WPF 会变得困难,而有时它是小菜一碟。
  • 你知道为什么 Datacontext 的行为是这样的,但只是针对我的 Usercontrol 而不是针对其他控件?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 2023-03-26
相关资源
最近更新 更多