2

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

具体来说,我创建了一个简单的用户控件,其中包含一个标签和一个按钮。对于这个用户控件,我创建了一个 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 = ...,但是,状态是由枚举设置的,因此不能真正绑定到按钮的背景属性。

我与此相关的问题:

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

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

4

3 回答 3

2

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

建议为此任务使用值转换器,为枚举的每个可能值返回一个画笔。这样,您的视图模型不需要知道任何关于颜色或画笔的信息,并且您可以在任何您想可视化状态的地方使用转换器。

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();
  }
}

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

你的实现对我来说似乎很好。您可能希望通过依赖注入消除视图模型和视图(当前持有对视图模型的引用)之间的耦合。但这取决于您的用例和您要使用的架构。

于 2012-06-18T19:59:22.950 回答
1

就个人而言,我无法将自定义 UserControls 与 MVVM 一起使用。要么我的想法还没有考虑如何将它们一起使用,要么它们只是不混合。我将 DataTemplates 用于不是窗口的所有内容。

保持简洁...

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}" />

如果需要,提供说明。

于 2012-06-18T20:08:43.153 回答
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" />

在虚拟机中:

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

      ButtonBg = Colors.Red;
   }    
}

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

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

于 2012-06-18T20:17:12.990 回答