c# - 在 UserControls( View )MVVM Prism 之间传递 ModelData(上下文)

标签 c# wpf mvvm prism

我正在做一个项目,我有三个 ViewModel: ObjectDetailsViewMode 有一个 ObjectBase 类型的上下文(属性链接到模型); PropertyTextViewModel 有一个PropertyText 类型的上下文,而PropertyNumberViewModel 有一个PropertyNumber 类型的上下文。

下面是模型的结构:

public class ObjectBase : ModelBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { SetProperty(ref _name, value); }
    }

    public DataCollection<PropertyBase> Properties { get; } = new DataCollection<PropertyBase>();
}

public class PropertyText : PropertyBase
{
    private string _default;
    public string Default
    {
        get { return _default; }
        set { SetProperty(ref _default, value); }
    }
}

public class PropertyNumber : PropertyBase
{
    private double _default = 0;
    public double Default
    {
        get { return _default; }
        set { SetProperty(ref _default, value); }
    }

    private double _minValue = 0;
    public double MinValue
    {
        get { return _minValue; }
        set { SetProperty(ref _minValue, value); }
    }

    private double _maxValue = 0;
    public double MaxValue
    {
        get { return _maxValue; }
        set { SetProperty(ref _maxValue, value); }
    }
}

关于 View ,我对每个 ViewModel 都有一个。 ObjectDetailsView 是一个使用控件,它具有一个用于编辑 Object.Name 的 TextBox、两个用于将新 PropertyText/PropertyNumber 添加到 Object.Properties 的按钮以及一个连接到该 Object.Properties 的 ItemsControl。

ItemsControl (ItemsSource) 中的每个 PropertyBase 都使用 DataTemplate 标记解析为一个新 View :
<ItemsControl ItemsSource="{Binding Object.Properties}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type models:PropertyText}">
            <views:PropertyTextView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type models:PropertyNumber}">
            <views:PropertyNumberView />
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

当我使用 PRISM 时,会自动为我创建正确的 ViewModel,然后将 View DataContext 设置为新的 ViewModel。我的问题是我需要将 Object.Properties 列表中的新属性传递给新创建的 View 的 ViewModel 并将其存储在我在那里的 Context 属性中。

我无法避免为每种属性类型创建一个 View / View 模型,因为某些属性类型(不是我在这里描述的类型)有一些底层逻辑。但我还有其他类型,如 bool 、引用、枚举。 .)

所以我真的需要将一个值传递给我尝试使用的 ViewModel
<ItemsControl ItemsSource="{Binding Object.Properties}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type models:PropertyText}">
            <views:PropertyTextView Context="{Binding}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type models:PropertyNumber}">
            <views:PropertyNumberView Context="{Binding}"/>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

请注意,Context 是我在 ViewModel 中创建的用于存储 ModelContext 的自定义属性。我什至在 View 的后台代码中创建了一个 DependencyProperty:
    public PropertyBase Context
    {
        get { return (PropertyBase)GetValue(ContextProperty); }
        set { SetValue(ContextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ContextProperty =
        DependencyProperty.Register("Context", typeof(PropertyBase), typeof(PropertyTextView), new PropertyMetadata(null));

但它没有链接到 ViewModels 设置事件(我在那里做了一个断点......什么都没有)。我什至在 PropertyTextView 代码隐藏(构造函数)中尝试了 SetBinding:
string propertyInViewModel = "Context";
var bindingViewMode = new Binding(propertyInViewModel) { Mode = BindingMode.TwoWay };
this.SetBinding(ContextProperty, bindingViewMode);

这些都没有运气......我真的卡住了。

更简单的东西

如果 PropertyTextView 有这个依赖属性。
    public string Context
    {
        get { return (PropertyBase)GetValue(ContextProperty); }
        set { SetValue(ContextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Context.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ContextProperty =
        DependencyProperty.Register("Context", typeof(string), typeof(PropertyTextBuilderView), new PropertyMetadata(null));

我应该能够做到:

对?!为什么不调用公共(public)属性“上下文”(我在那里放置了一个断点,但什么也没得到)。

最佳答案

而不是仅仅设置Context您的 View 属性为新的 Binding您需要分配当前 DataContext像这样:
<views:PropertyNumberView Context="{Binding .}"/>
这应该分配当前 Views.DataContext属性到您的新 View 。

如果您在 DataTemplate 中,您可能需要指定 RelativeSource :
<views:PropertyNumberView Context="{Binding Path=DataContext, RelativeSource={RelativeSource AncestorType=UserControl}}<ItemsControl ItemsSource="{Binding Object.Properties}"> <ItemsControl.Resources> <DataTemplate DataType="{x:Type models:PropertyText}"> <views:PropertyTextView Context="{Binding .}"/> </DataTemplate> <ItemsControl.Resources> </ItemsControl>

关于c# - 在 UserControls( View )MVVM Prism 之间传递 ModelData(上下文),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48685038/

相关文章:

c# - ASP.NET Core 和 CreateErrorResponse

c# - 使用 Json.NET 序列化/反序列化具有混合类型的数组

.net - 带边距的分组 WPF ListView 样式问题

c# - 如果 WPF comboBox 中有相同的项目,则不会触发 SelectionChanged 事件

c# - 谁首先创建依赖注入(inject)对象

wpf - 如何将命令附加到 CheckBox 的选中和取消选中?

c# - 合并两个字典对 c# 不是纯 concat

c# - 异步线程

c# - 如何以编程方式取消选中 ToggleButton

c# - 将 TextBlock 的可见性绑定(bind)到 TextBox