【问题标题】:Converting DataContext to a Local Value将 DataContext 转换为本地值
【发布时间】:2017-06-24 01:57:26
【问题描述】:

如何将设计器中DataContext 的属性更改传播到实际的数据上下文对象?这可能吗?

这是我尝试过的 - 我将 DataContext 转换为 XML 中的本地值 - 我认为我在设计器中对其所做的任何更改都会反映在 DataContext 对象上。

这是 SSCCE。我有一个名为 MammalUC 的 UserControl 和一个名为 Kangaroo 的类。我使用 Kangaroo 类的对象作为 DataContext。下面的代码说明了这一点。

using System.ComponentModel;
using System.Windows.Controls;

namespace WPFTestABC
{
    /// <summary>
    /// User Control :  Interaction logic for MammalUC.xaml
    /// </summary>
    public partial class MammalUC : UserControl
    {
        public MammalUC()
        {
            InitializeComponent();
            Kang = new Kangaroo();
            this.DataContext = Kang;
        }

        private Kangaroo kang;

        /// <summary>
        /// This is the datacontext.
        /// </summary>
        [Category("ForDebug")]
        [TypeConverter(typeof(ExpandableObjectConverter))]
        public Kangaroo Kang
        {
            get{ return kang;}
            set {kang = value;}
        }
    }

    /// <summary>
    /// Kangaroo class.
    /// </summary>
    public class Kangaroo : INotifyPropertyChanged
    {
        private int age;
        public int Age
        {
            get { return age; }
            set
            {
                age = value;
                OnPropertyChanged("Age");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string name)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(name));
            }
        }
    }
}

我像这样将 Age 属性绑定到 UserControl -

<UserControl x:Class="WPFTestABC.MammalUC"
             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:WPFTestABC"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <TextBox Text="{Binding Age}" Background="#FFD88787"></TextBox>
    </Grid>
</UserControl>

然后我将 MammalUC 放在窗户上。然后将 Kang 对象转换为本地值(我也尝试过作为静态资源)。在设计器属性网格中,我更改了值,但我没有看到正在更新的值。

<Window x:Class="WPFTestABC.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPFTestABC"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <!--<Window.Resources>
        <local:Kangaroo x:Key="Kangaroo1" Age="65"/>
    </Window.Resources>-->
    <Grid>
        <!--Using Static Resource -->
        <local:MammalUC HorizontalAlignment="Left" Height="100" Margin="210,115,0,0" VerticalAlignment="Top" Width="100">
            <!--Converting to local resource-->
            <local:MammalUC.Kang>
                <local:Kangaroo Age="85"/> <!--Value never updates-->
            </local:MammalUC.Kang>
        </local:MammalUC>
    </Grid>
</Window>

【问题讨论】:

  • 如何将给定对象的属性更改传播到对象本身?这是没有意义的。它它自己。
  • @Ed - 也许我应该更好地表达这个问题。为什么更改未注册? UI 没有更新。
  • 我知道我几天前回答了你的一个问题,你没有费心接受它是正确的,尽管你似乎认为它已经解决了你的问题。如果答案解决了您遇到的问题,您应该接受它。
  • @Ed - 很抱歉。我错过了。将您的解决方案标记为答案。会做得更好。
  • @SanMor,DataContext 对象的附加属性有什么好处? &lt;local:MammalUC.DataContext&gt;&lt;local:Kangaroo Age="85"/&gt;&lt;/local:MammalUC.DataContext&gt;。 DataContext 可以包含任何对象并通过绑定直接访问

标签: wpf datacontext


【解决方案1】:

然后将Kang对象转换为局部值

我无法很好地猜测您要在那里说什么。我没有看到任何对象被转换为任何东西,我不知道您所说的“本地值”是什么意思。我不知道你认为你在做什么。

但这就是你正在做的事情:

<!--Using Static Resource -->
<local:MammalUC HorizontalAlignment="Left" Height="100" Margin="210,115,0,0" VerticalAlignment="Top" Width="100">
    <!--Converting to local resource-->
    <local:MammalUC.Kang>
        <local:Kangaroo Age="85"/> <!--Value never updates-->
    </local:MammalUC.Kang>
</local:MammalUC>

此 XAML 中没有“静态资源”,也没有“本地资源”。 You should find out what the word "resource" means in WPF

您正在做的是替换Kang 属性的现有值与Kangaroo 类的新实例。

为什么这不起作用?原因如下:

    private Kangaroo kang;

    /// <summary>
    /// This only becomes the datacontext if you explicitly assign it 
    /// to this.DataContext.
    /// </summary>
    [Category("ForDebug")]
    [TypeConverter(typeof(ExpandableObjectConverter))]
    public Kangaroo Kang
    {
        get{ return kang;}
        set {kang = value;}
    }

你从来没有告诉任何人你改变了它。您没有更新数据上下文。回到构造函数中,您将DataContext 设置为Kang那个时刻的值。当你给Kang 一个新值时会发生什么?没什么。它设置私有kang,就是这样。当然它不会更新DataContext;你从来没有告诉过它。

KangarooAge 属性在更改时会引发 PropertyChanged,因此可以正常工作。 Kang 没有什么可比的。现在,控件不使用INotifyPropertyChanged;他们使用依赖属性。依赖属性在更改时也会引发通知事件,但您也可以在 XAML 中对它们进行绑定,因此它们更适合控件。

您可以添加Kangaroo 类型的新依赖属性并让它更新DataContext,但有一种更简单的方法可以做到这一点。

您可以执行以下操作来解决此问题:删除private Kangaroo kang; 并按如下方式更改属性。

    public Kangaroo Kang
    {
        get { return (Kangaroo)DataContext; }
        set { DataContext = value;}
    }

    public MammalUC()
    {
        InitializeComponent();

        //  This sets the DataContext. 
        Kang = new Kangaroo();
    }

DataContext 是一个依赖属性。设置它,通知将在幕后飞行。事情会发生。

您不能将Kang 设为绑定目标。为此,您必须将其设为依赖属性:

#region Kang Property
public Kangaroo Kang
{
    get { return (Kangaroo)GetValue(KangProperty); }
    set { SetValue(KangProperty, value); }
}

public static readonly DependencyProperty KangProperty =
    DependencyProperty.Register(nameof(Kang), typeof(Kangaroo), typeof(MammalUC),
        new PropertyMetadata(null));
#endregion Kang Property

XAML:

<UserControl 
    x:Class="WPFTestABC.MammalUC"
    ...blah blah blah...
    DataContext="{Binding Kang, RelativeSource={RelativeSource Self}}"
    >

然后你可以给你的主视图模型一个public Kangaroo SelectedKangaroo { /* INPC garble */ } 属性,并将它绑定到你的主窗口中:

<local:MammalUC Kang="{Binding SelectedKangaroo}" />

【讨论】:

  • @SanMor 不错。
  • 所以,从您真正解释得很好的解决方案中脱颖而出 - 我没有更新 DataContext,并且“在那一刻”的话非常有意义。我确实尝试了这两种解决方案,它们都有效,我确实对 Dependency Property 解决方案进行了小编辑。现在对 DataContext 对象的任何编辑都会反映在 UI 中,这就是我所追求的。我试图让康成为绑定的目标,然后我看到了你的编辑。谢谢!
猜你喜欢
  • 2015-11-16
  • 2012-04-22
  • 1970-01-01
  • 2012-08-28
  • 2013-05-26
  • 1970-01-01
  • 1970-01-01
  • 2014-11-07
  • 2011-04-23
相关资源
最近更新 更多