如何将设计器中DataContext
的属性更改为实际的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>
答案 0 :(得分:2)
然后将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
;你从来没有告诉过它。
Age
Kangaroo
属性在PropertyChanged
更改时会引发Kang
,因此可行。与INotifyPropertyChanged
没有任何可比性。现在,控件不使用Kangaroo
;他们使用依赖属性。依赖属性还会在更改时引发通知事件,但您也可以在XAML中对它们进行绑定,因此它们更适合于控件。
您可以添加类型为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
成为绑定的目标。为此,你必须去做一个依赖属性:
<UserControl
x:Class="WPFTestABC.MammalUC"
...blah blah blah...
DataContext="{Binding Kang, RelativeSource={RelativeSource Self}}"
>
XAML:
public Kangaroo SelectedKangaroo { /* INPC garble */ }
然后你可以给你的主视图模型一个<local:MammalUC Kang="{Binding SelectedKangaroo}" />
属性,并将它绑定在你的主窗口中:
{{1}}