我正在开始使用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属性。
我的问题与此相关:
我的控制方式是否正确?如果没有,在用户控件中实现数据绑定的正确方法是什么?
如何让我的枚举状态使用绑定更新按钮的背景属性?
答案 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>