MVVM使用代码隐藏或viewmodel操作视图

时间:2017-02-07 08:31:51

标签: c# wpf xaml mvvm

我正在使用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模式中哪种方法更好?

2 个答案:

答案 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中,而不是其他地方。