【问题标题】:Setting WPF datacontext for a specific control为特定控件设置 WPF 数据上下文
【发布时间】:2013-12-27 02:27:15
【问题描述】:

我正在开发一个 WPF 应用程序,我正在努力理解 DataContext 的一些细节,因为它适用于绑定。我的应用程序使用如下定义的业务对象:

public class MyBusinessObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, e);
        }
    }

    // enumerations for some properties
    public enum MyEnumValues
    {
        [Description("New York")]
        NewYork,
        [Description("Chicago")]
        Chicago,
        [Description("Los Angeles")]
        LosAngeles
    }

    // an example property
    private string _myPropertyName;
    public string MyPropertyName
    {
        get { return _myPropertyName; }
        set
        {
            if (_myPropertyName == value)
            {
                return;
            }

            _myPropertyName = value;
            OnPropertyChanged(new PropertyChangedEventArgs("MyPropertyName"));
        }
    }

    // another example property
    private MyEnumValues _myEnumPropertyName;
    public MyEnumValues MyEnumPropertyName
    {
        get { return _myEnumPropertyName; }
        set
        {
            if (_myEnumPropertyName== value)
            {
                return;
            }

            _myEnumPropertyName= value;
            OnPropertyChanged(new PropertyChangedEventArgs("MyEnumPropertyName"));
        }
    }

    // example list property of type Widget
    public List<Widget> MyWidgets { get; set; }

    // constructor
    public MyBusinessObject()
    {
        // initialize list of widgets
        MyWidgets = new List<Widget>();

        // add 10 widgets to the list
        for (int i = 1; i <= 10; i++)
        {
           MyWidgets.Add(new Widget());
        }

        // set default settings
        this.MyPropertyName = string.empty;
    }
}

如您所见,我在此类中声明了一些属性,其中一个是小部件列表。 Widget 类本身也实现了 INotifyPropertyChanged 并公开了大约 30 个属性。

我的 UI 有一个组合框,它绑定到我的小部件列表,如下所示:

MyBusinessObject myBusinessObject = new MyBusinessObject();

public MainWindow()
{
    InitializeComponent();

    this.DataContext = myBusinessObject;

    selectedWidgetComboBox.ItemsSource = myBusinessObject.MyWidgets;
    selectedWidgetComboBox.DisplayMemberPath = "WidgetName";
    selectedWidgetComboBox.SelectedValuePath = "WidgetName";
}

我的 UI 上的大多数控件都用于显示 Widget 的属性。当我的用户从组合框中选择一个小部件时,我希望这些控件显示所选小部件的属性。我目前正在通过在组合框的 SelectionChanged 事件处理程序中更新窗口的 DataContext 来实现此行为,如下所示:

private void selectedWidgetComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    this.DataContext = selectedWidgetComboBox.SelectedItem;
}

这允许我将我的控件绑定到适当的 Widget 属性,如下所示:

<TextBox Text="{Binding WidgetColor}"></TextBox>

但是,并非我的 UI 中的所有控件都用于显示 Widget 属性。某些控件需要显示来自 MyBusinessObject 的属性(例如:上面定义的 MyPropertyName)。在这种情况下,我不能简单地说:

<TextBox Text="{Binding MyPropertyName}"></TextBox>

...因为窗口的DataContext 指向的是选定的Widget 而不是MyBusinessObject。谁能告诉我如何为特定控件(在 XAML 中)设置 DataContext 以引用 MyPropertyName 是 MyBusinessObject 的属性这一事实?谢谢!

【问题讨论】:

  • 您是否考虑将对象属性添加到 Widget 类?并在选择更改时对其进行操作?

标签: wpf xaml data-binding datacontext


【解决方案1】:

试试

<TextBox Text="{Binding MyBusinessObject.MyPropertyName}"></TextBox>

如果 MyBusinessObject 是文本框的数据上下文并且 MyPropertyName 是 MyBusinessObject 的属性,则此方法有效

另外,Here is a good article to clarify binding

希望对你有帮助

编辑 1:

使用这样的相对绑定:

text="{Binding DataContext.MyPropertyName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TypeOfControl}}}"

因此,相对绑定允许您将可视化树查找到另一个 UI 元素并使用其数据上下文。我会考虑将您窗口的内容包装在网格中。并将您的 Windows 数据上下文润湿到业务对象,并将网格数据上下文润湿到小部件。这样,您始终可以通过实时源绑定使用父窗口的数据上下文。

如果您的窗口的数据上下文是您的业务对象,请使用以下内容

text="{Binding DataContext.MyPropertyName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"

【讨论】:

  • @J - 感谢您的回复。我正在将窗口的 DataContext 设置为选定的小部件。由于大多数控件都用于显示 Widget 属性,我认为这是最有意义的。不幸的是,我仍然有一些控件需要绑定到 MyBusinessObject 上的属性。据我了解,当我设置窗口的 DataContext 时,文本框的 DataContext 也设置为选定的小部件(因为文本框在窗口中)。我试图弄清楚如何将文本框的 DataContext 设置回 MyBusinessObject 但还没有运气。
  • 我希望我能给这个答案投票 100 次。我花了几个小时解决一个问题,这个答案解决了它。谢谢@JKing
【解决方案2】:

您应该像这样向 MyBusinessObject 类添加一个属性,而不是更改窗口的 DataContext:

private Widget _selectedWidget;
public Widget SelectedWidget
{
    get { return _selectedWidget; }
    set
    {
        if (_selectedWidget == value)
        {
            return;
        }

        _selectedWidget = value;
        OnPropertyChanged(new PropertyChangedEventArgs("SelectedWidget"));
    }
}

然后将 SelectedWidget 绑定到组合框的 SelectedItem 属性。您可以在任何需要使用小部件属性的地方执行此操作:

<TextBox Text="{Binding Path=SelectedWidget.WidgetColor}"></TextBox>

【讨论】:

    猜你喜欢
    • 2012-12-16
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多