如何在不清除依赖属性的情况下设置DataContext?
我正在使用视图模型模式,因此自定义用户控件的 DataContext 实际上是真实数据的视图模型包装器。
我的自定义控件可以包含自定义控件的分层实例。
我在自定义控件中为实际数据设置了 DependencyProperty,希望在通过绑定设置该数据时为该数据创建一个新的视图模型,然后将用户控件的数据上下文设置为新的视图模型。但是,设置 DataContext 属性似乎会导致我的真实数据 DependencyProperty 变得无效并设置为 null。有人知道解决这个问题的方法,或者更确切地说,我应该使用视图模型的正确方法吗?
我正在尝试做的事情的修剪样本:
用户控件:
public partial class ArchetypeControl : UserControl
{
public static readonly DependencyProperty ArchetypeProperty = DependencyProperty.Register(
"Archetype",
typeof(Archetype),
typeof(ArchetypeControl),
new PropertyMetadata(null, OnArchetypeChanged)
);
ArchetypeViewModel _viewModel;
public Archetype Archetype
{
get { return (Archetype)GetValue(ArchetypeProperty); }
set { SetValue(ArchetypeProperty, value); }
}
private void InitFromArchetype(Archetype newArchetype)
{
if (_viewModel != null)
{
_viewModel.Destroy();
_viewModel = null;
}
if (newArchetype != null)
{
_viewModel = new ArchetypeViewModel(newArchetype);
// calling this results in OnArchetypeChanged getting called again
// with new value of null!
DataContext = _viewModel;
}
}
// the first time this is called, its with a good NewValue.
// the second time (after setting DataContext), NewValue is null.
static void OnArchetypeChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args )
{
var control = (ArchetypeControl)obj;
control.InitFromArchetype(args.NewValue as Archetype);
}
}
viewmodel:
class ArchetypeComplexPropertyViewModel : ArchetypePropertyViewModel
{
public Archetype Value { get { return Property.ArchetypeValue; } }
}
XAML:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding ViewModelType}" Value="{x:Type c:ArchetypeComplexPropertyViewModel}">
<Setter Property="Template" Value="{StaticResource ComplexPropertyTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="ComplexPropertyTemplate" TargetType="{x:Type TreeViewItem}">
<Grid>
<c:ArchetypeControl Archetype="{Binding Value}" />
</Grid>
</ControlTemplate>
I'm using a viewmodel pattern, so my DataContext for my custom user control is actually a viewmodel wrapper for the real data.
My custom control can contain hierarchal instances of the custom control.
I set up a DependencyProperty in the custom control for the real piece of data, with the hopes of creating a new viewmodel for that data when it gets set via binding, and then setting the user control's datacontext to the new viewmodel. However, it seems that setting the DataContext property causes my real data DependencyProperty to become invalidated and set to null. Anyone know a way around this, or rather a proper way I should be using viewmodels?
Trimmed samples of what I'm trying to do:
The user control:
public partial class ArchetypeControl : UserControl
{
public static readonly DependencyProperty ArchetypeProperty = DependencyProperty.Register(
"Archetype",
typeof(Archetype),
typeof(ArchetypeControl),
new PropertyMetadata(null, OnArchetypeChanged)
);
ArchetypeViewModel _viewModel;
public Archetype Archetype
{
get { return (Archetype)GetValue(ArchetypeProperty); }
set { SetValue(ArchetypeProperty, value); }
}
private void InitFromArchetype(Archetype newArchetype)
{
if (_viewModel != null)
{
_viewModel.Destroy();
_viewModel = null;
}
if (newArchetype != null)
{
_viewModel = new ArchetypeViewModel(newArchetype);
// calling this results in OnArchetypeChanged getting called again
// with new value of null!
DataContext = _viewModel;
}
}
// the first time this is called, its with a good NewValue.
// the second time (after setting DataContext), NewValue is null.
static void OnArchetypeChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args )
{
var control = (ArchetypeControl)obj;
control.InitFromArchetype(args.NewValue as Archetype);
}
}
The viewmodel:
class ArchetypeComplexPropertyViewModel : ArchetypePropertyViewModel
{
public Archetype Value { get { return Property.ArchetypeValue; } }
}
The XAML:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding ViewModelType}" Value="{x:Type c:ArchetypeComplexPropertyViewModel}">
<Setter Property="Template" Value="{StaticResource ComplexPropertyTemplate}" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="ComplexPropertyTemplate" TargetType="{x:Type TreeViewItem}">
<Grid>
<c:ArchetypeControl Archetype="{Binding Value}" />
</Grid>
</ControlTemplate>
This problem was mentioned in the comments of Cannot databind DependencyProperty but never resolved
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
通过这样做:
您将您的
Archetype
属性绑定到数据上下文中名为Value
的属性。通过将数据上下文更改为新的ArchetypeViewModel
,您可以有效地对绑定进行新的评估。您需要确保新的ArchetypeViewModel
对象具有非空的Value
属性。如果没有看到更多代码(特别是
ArchetypeComplexPropertyViewModel
和ArchetypePropertyViewModel
的定义),我真的无法说出造成这种情况的原因是什么。By doing this:
You are binding your
Archetype
property to the property calledValue
on your data context. By changing your data context to the newArchetypeViewModel
you effectively cause a new evaluation of the binding. You need to make sure that the newArchetypeViewModel
object has a non-nullValue
property.Without seeing the more of your code (specifically, the definitions of
ArchetypeComplexPropertyViewModel
andArchetypePropertyViewModel
) I can't really say what is the cause of this.