如何在不清除依赖属性的情况下设置DataContext?

发布于 2024-08-17 09:20:37 字数 2650 浏览 8 评论 0原文

我正在使用视图模型模式,因此自定义用户控件的 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>

无法数据绑定 DependencyProperty 但从未解决

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

画▽骨i 2024-08-24 09:20:37

通过这样做:

<c:ArchetypeControl Archetype="{Binding Value}" />

您将您的 Archetype 属性绑定到数据上下文中名为 Value 的属性。通过将数据上下文更改为新的 ArchetypeViewModel,您可以有效地对绑定进行新的评估。您需要确保新的 ArchetypeViewModel 对象具有非空的 Value 属性。

如果没有看到更多代码(特别是 ArchetypeComplexPropertyViewModelArchetypePropertyViewModel 的定义),我真的无法说出造成这种情况的原因是什么。

By doing this:

<c:ArchetypeControl Archetype="{Binding Value}" />

You are binding your Archetype property to the property called Value on your data context. By changing your data context to the new ArchetypeViewModel you effectively cause a new evaluation of the binding. You need to make sure that the new ArchetypeViewModel object has a non-null Value property.

Without seeing the more of your code (specifically, the definitions of ArchetypeComplexPropertyViewModel and ArchetypePropertyViewModel) I can't really say what is the cause of this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文