当我想将整个视图更改为另一个视图时,我想知道正确的 MVVM 方法是什么。
我主要关心的是将用户控件的
DataContext
设置为首选视图模型。我读到直接设置 DataContext
并不总是最好的主意,所以我想知道我还能怎么做,还有什么替代方案?
我尝试在网上寻找好的解决方案,但到目前为止还没有找到好的答案。
我认为您的问题与在应用程序中实现导航的主题有关。主要有两种方法:
带有显式可更改 UserControl 的简单 UI 导航器示例:
/// <summary>A type containing a UserControl and its name.</summary>
public class NameForUC
{
/// <summary>Display name.</summary>
public string DisplayName { get; set; }
/// <summary>UserControl</summary>
public UserControl Value { get; set; }
}
<Window x:Class="CyberForum.UIListBoxNavigator.ListBoxNavigator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CyberForum.UIListBoxNavigator"
mc:Ignorable="d"
Title="ListBoxNavigator" Height="450" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="4*"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="listBox" DisplayMemberPath="DisplayName"
SelectedIndex="0">
<local:NameForUC DisplayName="Begin">
<local:NameForUC.Value>
<local:OnePageUC/>
</local:NameForUC.Value>
</local:NameForUC>
<local:NameForUC DisplayName="End">
<local:NameForUC.Value>
<local:TwoPageUC/>
</local:NameForUC.Value>
</local:NameForUC>
</ListBox>
<ContentPresenter Grid.Column="1"
Content="{Binding SelectedItem, ElementName=listBox}">
<ContentPresenter.ContentTemplate>
<DataTemplate DataType="local:NameForUC">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding DisplayName}" HorizontalAlignment="Center"/>
<ContentPresenter Grid.Row="1" Content="{Binding Value}"/>
</Grid>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</Grid>
</Window>
您可以从这里获取实施细节和带有源代码的项目(俄语主题):https://www.cyberforum.ru/wpf-silverlight/thread2564584.html#post14145160
如果您提供有关任务的更多详细信息和解释,提供 ViewModel 和 View 的最小示例,并解释您希望它们如何交互,我相信您可以获得更具体的建议,以专门针对您的任务选择实现选项。
这是根据当前数据上下文的类型实现视图更改的另一个示例。
namespace Core2023.Navigators
{
public class LocatorNavigator : ViewModelBase
{
public object Current { get => Get<object>(); set => Set(value); }
public RelayCommand SetCurrent => GetCommand<object>(obj => Current = obj);
}
public class TextVM
{
public string Text { get; set; } = string.Empty;
}
public class NumberVM
{
public int Number { get; set; }
}
}
<Application.Resources>
<navigators:TextVM x:Key="textVM" Text="navigators:TextVM x:Key=textVM"/>
<navigators:NumberVM x:Key="numberVM" Number="999888"/>
<navigators:LocatorNavigator
x:Key="navigator"
Current="{StaticResource textVM}"/>
<UserControl x:Class="Core2023.Navigators.TextUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Core2023.Navigators"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<d:UserControl.DataContext>
<local:TextVM Text="Some Text"/>
</d:UserControl.DataContext>
<UniformGrid Background="LightYellow"
Rows="1">
<Viewbox>
<TextBlock Margin="10">
<Run Text="Text:"/>
<Run Text="{Binding Text, Mode=OneWay}"/>
</TextBlock>
</Viewbox>
<Viewbox>
<Button Margin="10"
Content="Go to NumberVM"
Command="{Binding SetCurrent, Source={StaticResource navigator}}"
CommandParameter="{StaticResource numberVM}"/>
</Viewbox>
</UniformGrid>
</UserControl>
<UserControl x:Class="Core2023.Navigators.NumberUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Core2023.Navigators"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<d:UserControl.DataContext>
<local:NumberVM Number="12345678"/>
</d:UserControl.DataContext>
<UniformGrid Background="LightCoral"
Rows="1">
<Viewbox>
<TextBlock Margin="10">
<Run Text="Number:"/>
<Run Text="{Binding Number, Mode=OneWay}"/>
</TextBlock>
</Viewbox>
<Viewbox>
<Button Margin="10"
Content="Go to TextVM"
Command="{Binding SetCurrent, Source={StaticResource navigator}}"
CommandParameter="{StaticResource textVM}"/>
</Viewbox>
</UniformGrid>
</UserControl>
<Window x:Class="Core2023.Navigators.TextNumberWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Core2023.Navigators"
mc:Ignorable="d"
Title="TextNumberWindow" Height="450" Width="800"
Content="{Binding Current, Source={StaticResource navigator}}">
<Window.Resources>
<DataTemplate DataType="{x:Type local:TextVM}">
<local:TextUserControl/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:NumberVM}">
<local:NumberUserControl/>
</DataTemplate>
</Window.Resources>
</Window>
如果数据上下文类型相同,并且需要根据数据上下文属性的值来选择视图,那么最好使用DataTemplateSelector类