【问题标题】:WPF MVVM Lights - Same user control with different parameterWPF MVVM Lights - 具有不同参数的相同用户控件
【发布时间】:2018-02-23 07:23:48
【问题描述】:

我有一个使用 MVVM Light 的 WPF 应用程序。
一个 MainView (+ MainViewModel) 和一个用户控件 (+ UCViewModel)。

该应用程序将有一个带有 2 个选项卡项的选项卡控件。
每个选项卡都有一个用户控件(相同的用户控件)。

用户控件作业:加载文件的内容,显示内容(并允许用户将其导出到其他格式)。

当应用程序启动时,我将读取一个配置文件并将文件位置(来自配置文件)传递给每个用户控件(例如:File1Path、File2Path)。
我可以使用 MVVM Light Messenger.Default.Send 来完成这项工作(从 MainViewModelUCViewModel)。

我的问题是:如何区分哪个用户控件将获取哪个文件路径?

我在ViewModelLocator 中使用SimpleIoc.Default.Register 来注册我的MainViewModelUCViewModel
在注册时,我还没有 Config 文件中的数据,因此无法将其传递给 UCViewModel。

对我的问题有任何意见/解决方案吗?

【问题讨论】:

  • 在您设置 id 的位置创建新消息。 Id=1 将是 view1 的文件,Id=2 将是 id=2 的文件。或使用现有消息并发送 $"{filepath}, {id}"
  • @Marco,感谢您的建议。我也是这样想的。但是我的 UserControl ViewModel 只有一个,但 UserControl 出现在两个地方。如果我发送这样的 Id,两个 UserControl ViewModel 都会收到它,并且在那个 ViewModel 中,我不知道如何区分它。 (如果我理解错误,请纠正我)。
  • 每个文件都需要一个用户控件实例。这是肯定的。您可以简单地向视图模型的构造函数添加一个 id。就是这样。 id 将与消息的 id 匹配。
  • 你的意思是,我应该使用 MainViewModel 为每个用户控件创建实例,而不是使用 ViewModelLocator 吗? (抱歉这么多问题,我还在学习这个 MVVM Light 的阶段。)
  • 为什么不在 MainViewModel 中创建两个 UCViewModel 属性并与它们交互而不是发送消息?如果 TabControl 将始终包含两个 TabItem,则该数字无论如何都不是动态的,并且您知道总会有两个子 UC。

标签: c# wpf user-controls mvvm-light


【解决方案1】:

方法一(使用mm8的方式)

根据 @mm8 的建议,我最终将 MainViewModel 类中每个 UserControl 使用的 DataContext 声明为 Properties。

示例(在 MainView xaml 中):

<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" DataContext="{Binding UC2DC}" />

但是,为了让我支持我的设计时 XAML intelliense 支持,我仍然使用默认的 MVVM Light 方式的 DataContext 绑定。​​

示例:在 ViewModelLocator 中,

static ViewModelLocator()
{
    ....
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register<UCViewModel>();
    ....
}

public UCViewModel CM
{
    get
    {
        return ServiceLocator.Current.GetInstance<UCViewModel>();
    }
}

在 MainViewModel 中,

private UCViewModel _uC2DC;

public UCViewModel UC2DC
{
    get { return _uC2DC; }
    set { Set(ref _uC2DC, value); }
}

private UCViewModel _uC1DC;

public UCViewModel UC1DC
{
    get { return _uC1DC; }
    set { Set(ref _uC1DC, value); }
}

在我的 MainViewModel 的某个地方,我需要创建新实例并放入这些属性中。

完成所有操作后,我将删除/注释掉 User Control 默认的 MVVM Light DataContext 绑定、ViewModelLocator 的 SimpleIoc Register 和 GetInstance 属性等,它将更改为我的 MainView 数据绑定。

我不太确定 MVVM 方式是否可以,但到目前为止,它解决了我的问题。

方法2(使用Marco的方式)

在 Marco 示例代码之后,我开始知道我们可以使用一个键注册多个 ViewModel 实例来区分它们,并且在调用属性时,使用该键来拉出正确的一个。
下面是代码...

对于 ViewModelLocator

static ViewModelLocator()
{
    ...
    SimpleIoc.Default.Register<MainViewModel>();
    SimpleIoc.Default.Register(() => new UCViewModel(), "1");
    SimpleIoc.Default.Register(() => new UCViewModel(), "2");
    ...
}

public UCViewModel UCVM1
{
    get
    {
        return ServiceLocator.Current.GetInstance<UCViewModel>("1");
    }
}

public UCViewModel UCVM2
{
    get
    {
        return ServiceLocator.Current.GetInstance<UCViewModel>("2");
    }
}

在我的 MainView XAML 中

<TabControl>
    <TabItem Header="Test 1">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="70"/>
                <RowDefinition Height="70"/>
            </Grid.RowDefinitions>
            <v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" 
                DataContext="{Binding UCVM1,Source={StaticResource Locator}}" />
            ...
            ...
        </Grid>
    </TabItem>
    <TabItem Header="Test 2">
        <Grid Background="AliceBlue">
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="70"/>
                <RowDefinition Height="70"/>
            </Grid.RowDefinitions>
            <v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" 
                DataContext="{Binding UCVM2,Source={StaticResource Locator}}" />
            ...
            ...
        </Grid>
    </TabItem>
</TabControl>

对于这种方法,它仍然是相同的,在设计时,我们不能绑定到一个默认的 DataContext。可能是这种情况下的取舍。

【讨论】:

  • 我认为这行不通。 T你总是在这里获得相同的实例 ServiceLocator.Current.GetInstance();除非你使用 SimpleIoc.GetInstance(string key) 方法...
  • @Marco,在 ViewModelLocator 中,当我完成设计布局并从那里使用上面的代码时,我会注释掉那些 register 和 GetInstance 行。它正在工作。
  • 我已根据您的建议使用 SimpleIoc 方式进行了更新。谢谢。 @马可
猜你喜欢
  • 2012-12-01
  • 2017-10-23
  • 2012-06-24
  • 1970-01-01
  • 2014-07-15
  • 2015-01-28
  • 1970-01-01
  • 2017-12-25
  • 2018-11-14
相关资源
最近更新 更多