我正在使用MVVM编写应用程序,我有一个问题,如果我应该使用代码隐藏操作View,或者我应该将其留空。我想要做的是,当用户点击按钮时,隐藏的视图会滑出。目前我在视图模型中这样做。这是我的代码:
这是我的观点:
<Window.DataContext>
<ViewModels:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<Style x:Key="DockPanelStyle" TargetType="{x:Type DockPanel}" >
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Background" Value="AliceBlue"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding showView}"
Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
To="0,0,0,0"
AccelerationRatio=".25"
DecelerationRatio=".25"
Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
To="0,0,-400,0"
DecelerationRatio=".25"
AccelerationRatio=".25"
Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0">
<Label Content="Main view" HorizontalAlignment="Center" FontSize="42"/>
<Button Command="{Binding SlideOutCommand}" Content="Show view" FontSize="42"/>
</StackPanel>
<DockPanel
Grid.Column="1"
Margin="0,0,-400,0"
Style="{StaticResource DockPanelStyle}">
<Label Content="Sliding view" HorizontalAlignment="Center" FontSize="42"/>
</DockPanel>
</Grid>
</Window>
代码隐藏是空的。 这是我的ViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
showView = false;
}
public ICommand SlideOutCommand
{
get { return new ActionCommand(action => ShowView()); }
}
private void ShowView()
{
showView = true;
//Do some extra logic
}
private bool _showView;
public bool showView
{
get { return _showView; }
set
{
_showView = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
virtual protected void OnPropertyChanged([CallerMemberName]string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
或者我应该采用这样的解决方案:
查看:
<Window.DataContext>
<ViewModels:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<Style x:Key="DockPanelStyle" TargetType="{x:Type DockPanel}" >
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Background" Value="AliceBlue"/>
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=Tag, RelativeSource={RelativeSource Self}}"
Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
To="0,0,0,0"
AccelerationRatio=".25"
DecelerationRatio=".25"
Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation
Storyboard.TargetProperty="Margin"
To="0,0,-400,0"
DecelerationRatio=".25"
AccelerationRatio=".25"
Duration="0:0:0.5"
/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel
Grid.Column="0">
<Label Content="Main view" HorizontalAlignment="Center" FontSize="42"/>
<Button Command="{Binding SlideOutCommand}" Content="Show view" FontSize="42" Click="Button_Click"/>
</StackPanel>
<DockPanel
x:Name="SlideView"
Grid.Column="1"
Margin="0,0,-400,0"
Style="{StaticResource DockPanelStyle}"
Tag="{Binding Path=showView,RelativeSource={RelativeSource AncestorType=Window}}">
<Label Content="Sliding view" HorizontalAlignment="Center" FontSize="42"/>
</DockPanel>
</Grid>
</Window>
代码隐藏:
public partial class MainWindowView : Window, INotifyPropertyChanged
{
public MainWindowView()
{
InitializeComponent();
showView = false;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
showView = true;
}
private bool _showView;
public bool showView
{
get { return _showView; }
set
{
_showView = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
virtual protected void OnPropertyChanged([CallerMemberName]string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
和ViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
}
public ICommand SlideOutCommand
{
get { return new ActionCommand(action => ShowView()); }
}
private void ShowView()
{
//Do some extra logic
}
public event PropertyChangedEventHandler PropertyChanged;
virtual protected void OnPropertyChanged([CallerMemberName]string propName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
MVVM模式中哪种方法更好?
答案 0 :(得分:3)
有些人会告诉你,ViewModel会与模型和视图进行交互,但我不是其中之一。
如果您需要做的只是整容,并且不依赖于任何模型数据,我说您应该只在视图及其代码隐藏中处理它。
在viewmodel中使用这些仅限视图的数据会使它变得混乱,如果你的视图有点复杂,它会变得非常可怕。对我来说,这有点打破了分离所有层并保持一切尽可能干净的要点。
答案 1 :(得分:1)
对我来说,ViewModel应该处理与数据相关的任何逻辑。 例如:
public class OrderViewModel
{
/*
Other fields and properties
*/
public decimal Total
{
get
{
return this.Price * this.Quantity;
}
}
}
此处ViewModel包含用于计算订单总价的逻辑。但任何视觉表现都不应该在这里。 数据的直观表示应该在View中,而不是其他地方。