2015-12-17 83 views
5

我是MVVM模式中真正的初学者。我试图改变按钮的点击网格的背景。我有一个包含一个按钮的网格的xaml,以及一个ViewModel .cs,我想从中更改网格的按钮点击背景。直到有一次,我只是继承显示一个MessageBox当我点击...MVVM在点击时改变网格的背景颜色

的.xaml代码:

<Window x:Class="WpfSimple.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfSimple" 
    Title="MainWindow" Height="150" Width="370"> 
<Window.DataContext> 
    <local:MainWindowViewModel/> 
</Window.DataContext> 
    <Grid> 
    <Button Content="Click" 
      Height="23" 
      HorizontalAlignment="Left" 
      Background="Gray" 
      Margin="75.944,47.465,0,0" 
      Name="btnClick" 
      VerticalAlignment="Top" 
      Width="203" 
      Command="{Binding ButtonCommand}"/> 
     <!--What is necessary to add for changing grid color ? Commandparameter ?--> 
</Grid> 

MainWindowViewModel.cs代码:

namespace WpfSimple 
{ 
    class MainWindowViewModel 
    { 
     private ICommand m_ButtonCommand; 
     public ICommand ButtonCommand 
     { 
      get 
      { 
       return m_ButtonCommand; 
      } 
      set 
      { 
       m_ButtonCommand = value; 
      } 
     } 

     public MainWindowViewModel() 
     { 
      ButtonCommand=new RelayCommand(new Action<object>(ChangeBgColor)); 
     } 

     public void ChangeBgColor(object obj) 
     { 
      /*HERE I WANT TO CHANGE GRID COLOR*/ 
     } 
    } 
} 

对不起,我烂英文。

此致敬礼。

回答

1

Fitst大家应该实现在您的视图模型INotifyPropertyChanged

public class MainWindowViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    // This method is called by the Set accessor of each property. 
    // The CallerMemberName attribute that is applied to the optional propertyName 
    // parameter causes the property name of the caller to be substituted as an argument. 
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

然后,添加NotifyPropertyChanged()到你的属性二传手。

好的。接下来,网格背景颜色添加新的物业给您的视图模型:

private Brush _gridBackground; 
public Brush GridBackground 
{ 
    get { return _gridBackground; } 
    set 
    { 
     _gridBackground = value; 
     NotifyPropertyChanged(); 
    } 
} 

而网格的背景绑定到你的财产:

<Grid Background="{Binding GridBackground}"> 

最后你可以改变GridBackground在命令处理程序:

public void ChangeBgColor(object obj) 
{ 
    GridBackground = Brushes.Blue; 
} 

您应该记住,向您的代码添加像Brush这样的WPF类是一种不好的做法。更好的方法是在XAML代码中使用IValueConverter,并在ViewModel中使用BCL类。例如,您可以在ViewModel中使用枚举并将其转换为在ValueConverter中刷新。

  1. 您的视图模型的属性添加新的枚举:

    public enum GridState { Valid, Invalid } 
    
  2. 更改属性类型:

    private GridState _gridBackground; 
    public GridState GridBackground 
    { 
        get { return _gridBackground; } 
        set 
        { 
         _gridBackground = value; 
         NotifyPropertyChanged(); 
        } 
    } 
    
  3. 添加新的类值转换器

    public class GridStateToBackgroundColorConverter : IValueConverter 
    { 
        #region IValueConverter Members 
    
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
        { 
         GridState val = (GridState) value; 
         if(val == GridState.Valid) 
          return Brushes.Green; 
         return Brushes.Red; 
        } 
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
        { 
         throw new NotSupportedException(); 
        } 
    
        #endregion 
    } 
    
  4. 新的静态资源添加到您的控制

    <UserControl.Resources> 
        <converters:GridStateToBackgroundColorConverter x:Key="gridStateToBackgroundColorConverter" /> 
    </UserControl.Resources> 
    
  5. 更新。如果你想改变网格的背景颜色,那么你可以使用命令参数绑定到你的财产

    <Grid Background="{Binding GridBackground, Converter={StaticResource gridStateToBackgroundColorConverter}"> 
    
+0

是的!非常感谢Vadim Martynov!我不确定我是否理解“INotifyPropertyChanged接口”的目的,因为它没有通知我什么......但你的回答是非常有用的。 此致敬礼。 – Chefty

+0

@Chefty INPC是数据绑定所必需的。没有它,当你在ViewModel中改变属性时,你的颜色不会改变。而且,INPC是数据绑定的一般特征。你可以阅读更多关于MSDN:https://msdn.microsoft.com/en-US/library/ms752347(v=vs.100).aspx –

+0

我不能添加新的静态资源到我的控制,这是一个错误:“在WPF项目中不支持GridStateToBackgroundColorConverter“是否正常? – Chefty

-1

。您可以将任何UI控件作为Command参数传递。在你的情况通过网格访问您的视图模型中的网格。 为网格命名,并使用该名称作为命令参数。 为此,您需要实现这样的代码:

<Window x:Class="WpfSimple.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfSimple" 
     Title="MainWindow" Height="150" Width="370"> 
<Window.DataContext> 
    <local:MainWindowViewModel/> 
</Window.DataContext> 
<Grid Name="grid"> 
<Button Content="Click" 
     Height="23" 
     HorizontalAlignment="Left" 
     Background="Gray" 
     Margin="75.944,47.465,0,0" 
     Name="btnClick" 
     VerticalAlignment="Top" 
     Width="203" 
     Command="{Binding ButtonCommand}" 
     CommandParameter="{Binding Elementname="grid"}"/> 
</Grid> 

使此更改的.xaml文件后。实现参数化中继命令以使用此传递的网格在Viewmodel文件中使用。 实现参数relay命令尝试执行以下代码:

private ICommand m_ButtonCommand; 
    public ICommand ButtonCommand 
    { 
     get 
     { 
      return m_ButtonCommand; 
     } 
     set 
     { 
      m_ButtonCommand = value; 
     } 
    } 

    public MainWindowViewModel() 
    { 
     ButtonCommand=new RelayCommand<Grid>(ChangeBgColor); 
    } 

    public void ChangeBgColor(Grid grid) 
    { 
     if(grid!=null) 
      grid.Background = Brushes.Red; //Any color you want to change. 
    } 

我希望这会工作。谢谢。

+0

嗨!谢谢Dhruv Panchal,但这不行。 “RelayCommand ”发生错误,我无法解决它。 – Chefty

+0

@Chefty你正在得到哪个错误?你能告诉我吗?您是否在应用程序中实施了RelayCommand ? –

+0

有人告诉我,RelayCommand不能与类型参数一起使用。 – Chefty