WPF MVVM Lights - 具有不同参数的相同用户控件
WPF MVVM Lights - Same user control with different parameter
我有一个使用 MVVM Light 的 WPF 应用程序。
一个主视图 (+ MainViewModel) 和一个用户控件 (+ UCViewModel)。
该应用程序将有一个带有 2 个选项卡项的选项卡控件。
每个选项卡都会有一个用户控件(相同的用户控件)。
用户控制作业:加载文件内容,显示内容(并允许用户将其导出为其他格式)。
当应用程序启动时,我将读取配置文件并将文件位置(从配置文件)传递给每个用户控件(例如:File1Path、File2Path)。
我可以使用 MVVM Light Messenger.Default.Send
来完成这项工作(从 MainViewModel 到 UCViewModel)。
我的问题是:如何区分哪个用户控件将获得哪个文件路径?
我在 ViewModelLocator
中使用 SimpleIoc.Default.Register
来注册我的 MainViewModel 和 UCViewModel.
在注册的时候,我还没有Config文件的数据,所以我不能把它传递给UCViewModel。
我的问题有 comment/solution 吗?
方法一(采用mm8的方式)
按照 @mm8 的建议,我最终在我的 MainViewModel class 中为每个 UserControl 用法声明了 DataContext 作为属性。
示例(在 MainView xaml 中):
<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" DataContext="{Binding UC2DC}" />
但是,为了支持我的设计时间XAML intelliense 支持,我仍然使用DataContext 绑定的默认MVVM Light 方式。
示例:在 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 中的某处,我需要创建新实例并将其放入这些属性中。
完成所有操作后,我将 delete/comment 退出用户控件默认的 MVVM Light DataContext 绑定、ViewModelLocator 的 SimpleIoc 注册和 GetInstance 属性 等,它会更改为我的 MainView 数据绑定。
我不太确定 MVVM 方式是否可行,但截至目前,它解决了我的问题。
方法二(用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。可能这是对这种情况的妥协。
我有一个使用 MVVM Light 的 WPF 应用程序。
一个主视图 (+ MainViewModel) 和一个用户控件 (+ UCViewModel)。
该应用程序将有一个带有 2 个选项卡项的选项卡控件。
每个选项卡都会有一个用户控件(相同的用户控件)。
用户控制作业:加载文件内容,显示内容(并允许用户将其导出为其他格式)。
当应用程序启动时,我将读取配置文件并将文件位置(从配置文件)传递给每个用户控件(例如:File1Path、File2Path)。
我可以使用 MVVM Light Messenger.Default.Send
来完成这项工作(从 MainViewModel 到 UCViewModel)。
我的问题是:如何区分哪个用户控件将获得哪个文件路径?
我在 ViewModelLocator
中使用 SimpleIoc.Default.Register
来注册我的 MainViewModel 和 UCViewModel.
在注册的时候,我还没有Config文件的数据,所以我不能把它传递给UCViewModel。
我的问题有 comment/solution 吗?
方法一(采用mm8的方式)
按照 @mm8 的建议,我最终在我的 MainViewModel class 中为每个 UserControl 用法声明了 DataContext 作为属性。
示例(在 MainView xaml 中):
<v:UC Grid.Row="0" HorizontalAlignment="Stretch" Margin="10" DataContext="{Binding UC2DC}" />
但是,为了支持我的设计时间XAML intelliense 支持,我仍然使用DataContext 绑定的默认MVVM Light 方式。
示例:在 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 中的某处,我需要创建新实例并将其放入这些属性中。
完成所有操作后,我将 delete/comment 退出用户控件默认的 MVVM Light DataContext 绑定、ViewModelLocator 的 SimpleIoc 注册和 GetInstance 属性 等,它会更改为我的 MainView 数据绑定。
我不太确定 MVVM 方式是否可行,但截至目前,它解决了我的问题。
方法二(用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。可能这是对这种情况的妥协。