关于WPF MVVM和用户控件的新手问题

时间:2012-06-18 19:42:36

标签: wpf

我正在开始使用WPF,我在实现数据绑定方面遇到了一些困难。

具体来说,我创建了一个简单的用户控件,它包含一个Label和一个Button。 对于此用户控件,我创建了一个ViewModel,它只包含两个属性string“Text”和SimpleEnum“Status”。

控件的目的是显示某些内容的状态,例如“已连接”是/否等。按钮的背景颜色表示状态。

我的XAML看起来像这样

<Control.DataContext>
    <vm:OnOffStatusViewModel />
</Control.DataContext>

<Label x:Name="label1" Height="Auto" HorizontalAlignment="Left" Content="{Binding Text}" Width="280" />
<Button Style="{StaticResource GlassButton}" Height="14" Width="14" Background="{Binding Status}" Grid.Column="1" />

xmlns:vm="clr-namespace:Controls"

代码隐藏有一个属性ViewModel公开视图模型,实现INotifyPropertyChanged,并初始化为_viewModel = (OnOffStatusViewModel) DataContext;

现在,在我看来正在使用这个控件,我设法将Text设置为某个东西,因为我在我的实现视图中代码隐藏有onOffStatus1.ViewModel.Text = ...,但是,状态是由enum设置的,并且因此不能真正绑定到按钮的background属性。

我的问题与此相关:

  1. 我的控制方式是否正确?如果没有,在用户控件中实现数据绑定的正确方法是什么?

  2. 如何让我的枚举状态使用绑定更新按钮的背景属性?

3 个答案:

答案 0 :(得分:2)

  

如何让我的枚举状态使用绑定更新按钮的背景属性?

建议使用value converter执行此任务,为枚举的每个可能值返回画笔。这样,您的视图模型不需要了解有关颜色或画笔的任何信息,您可以在任何想要显示状态的地方使用转换器。

<强> XAML

<UserControl x:Class="WpfApplication1.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication1">

    <UserControl.Resources>
        <local:StatusColorConverter x:Key="StatusColorConverter" />
    </UserControl.Resources>

    <Button Background="{Binding Status, Converter={StaticResource StatusColorConverter}" />

</UserControl>

<强>转换器

public enum Status
{
  Connected
}

public class StatusColorConverter : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    switch ((Status)value)
    {
      case Status.Connected: return new SolidColorBrush(Colors.Green);
    }

    return new SolidColorBrush(Colors.Black);
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
    throw new NotImplementedException();
  }
}
  

我完成控制的方式是否正确?如果没有,那是什么   在用户控件中实现数据绑定的方法?

您的实施对我来说似乎没问题。您可能希望通过依赖注入消除视图模型与视图(当前包含对视图模型的引用)之间的耦合。但这取决于您的用例和您想要使用的架构。

答案 1 :(得分:1)

就个人而言,我无法在MVVM中使用自定义UserControls。要么我的思想没有围绕如何使用它们或者它们只是不混合。我将DataTemplates用于不是Window的所有内容。

保持简洁......

OnOffStatusVM : INPC
   string Status
   Color Color (or Brush)
   (set Color when enum value updates)

(OnOffStatus DataTemplate)
<DataTemplate DataType="{x:Type ViewModel:OnOffStatusVM}" x:Shared="False" x:Key="rezOnOffStatus">
   <Grid>   
      <Label Height="Auto" HorizontalAlignment="Left" Content="{Binding Status}" Width="280" />
      <Button Style="{StaticResource GlassButton}" Height="14" Width="14" Background="{Binding Color}" Grid.Column="1" />
   </Grid>
</DataTemplate>

如果DataContext派生自OnOffStatusVM

,则使用

<ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource rezOnOffStatus}" />

如果DataContext具有OnOffStatusVM OnOffStatus属性

,则使用

<ContentPresenter Content="{Binding OnOffStatus}" ContentTemplate="{StaticResource rezOnOffStatus}" />

如果需要,提供澄清..

答案 2 :(得分:1)

我会采用与此处其他答案略有不同的方法,我喜欢将代码和逻辑直接放入我的视图模型中,所以我会这样做:

<Control.DataContext>
    <vm:OnOffStatusViewModel />
</Control.DataContext>

<Label x:Name="label1" Height="Auto" HorizontalAlignment="Left" Content="{Binding Text}" Width="280" />
<Button Style="{StaticResource GlassButton}" Height="14" Width="14" Background="{Binding ButtonBg}" Grid.Column="1" />

在VM中:

public MyStatus Status
{
   get { return _status; }
   set
   {
      _status = value;
      OnPropertyChanged("Status");

      ButtonBg = Colors.Red;
   }    
}

public Color ButtonBg 
{
   get { ... }
   set { ... }
}

由于您的按钮背景绑定到视图模型上的属性,因此您可以自由地更改它以响应视图模型中发生的任何事情,而无需将逻辑或代码移动到转换器和模板。< / p>