【发布时间】:2019-11-29 01:50:23
【问题描述】:
我需要将我的代码设为 MVVM(这意味着没有植入代码隐藏),并且我想在任何点击上更改我的 LabelBackground >(即使我点击按钮)。
这意味着我需要从我的代码隐藏中删除我的 MainWindowView_OnPreviewMouseDown 和 MainWindowView_OnPreviewMouseUp。
这是我的工作项目:
代码隐藏
public partial class MainWindowView : Window
{
private readonly MainWindowViewModel _viewModel;
public MainWindowView()
{
InitializeComponent();
_viewModel = new MainWindowViewModel();
// The DataContext serves as the starting point of Binding Paths
DataContext = _viewModel;
}
private void MainWindowView_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
_viewModel.LabelBackground = Brushes.Black;
}
private void MainWindowView_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
_viewModel.LabelBackground = Brushes.Blue;
}
}
}
XAML
<Window x:Class="WpfExample.MainWindowView" PreviewMouseDown="MainWindowView_OnPreviewMouseDown" PreviewMouseUp="MainWindowView_OnPreviewMouseUp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfExample">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Command="{Binding HiButtonCommand}" CommandParameter="Hai" Content="click to hi"
Height="100" Margin="208,30,203,30" />
<Label Content="Disco Background" Background="{Binding LabelBackground}" Margin="208,66,203,69" Grid.Row="1"/>
</Grid>
</Window>
视图模型
class MainWindowViewModel : INotifyPropertyChanged
{
private ICommand hiButtonCommand;
public ICommand HiButtonCommand
{
get
{ return hiButtonCommand; }
set
{ hiButtonCommand = value; }
}
private SolidColorBrush labelBackground;
public SolidColorBrush LabelBackground
{
get { return labelBackground; }
set
{
if (labelBackground != value)
{
labelBackground = value;
OnPropertyChanged("LabelBackground");
}
}
}
public MainWindowViewModel()
{
HiButtonCommand = new RelayCommand(ShowMessage);
}
public void ShowMessage(object obj)
{
MessageBox.Show(obj.ToString());
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
最好的方法是什么?
编辑:
我尝试使用
EventTrigger方法,但对我来说效果不佳,因为 它不会改变标签背景,它会改变背景 取而代之的是窗口。有什么方法可以定位标签而不是 窗户?
XAML:
<Window x:Class="WpfExample.MainWindowView" PreviewMouseDown="MainWindowView_OnPreviewMouseDown" PreviewMouseUp="MainWindowView_OnPreviewMouseUp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:local="clr-namespace:WpfExample">
<Window.Triggers>
<EventTrigger RoutedEvent="Mouse.PreviewMouseDown">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Black"
Storyboard.TargetProperty="(Label.Background).(SolidColorBrush.Color)"
Duration="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.PreviewMouseUp">
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="Blue"
Storyboard.TargetProperty="(Label.Background).(SolidColorBrush.Color)"
Duration="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0" Command="{Binding HiButtonCommand}" CommandParameter="Hai" Content="click to hi" Height="100" Margin="208,30,203,30"/>
<Label Name="Label" Content="Disco Background" Background="White" Margin="208,66,203,59" Grid.Row="1"/>
</Grid>
</Window>
【问题讨论】:
-
MVVM 是关于将视图与模型分离。这与从视图或代码隐藏中消除 C# 无关。代码隐藏很好,但在有 XAML 解决方案时通常可以而且应该避免,因为 XAML 简单且易于阅读(因为标记反映了可视树结构)。 XAML 解析器为您做了很多工作,因此无需使用 C# 手动执行操作。有些事情必须在代码隐藏中完成。例如,大多数与控件的视觉效果没有直接关系的逻辑。避免代码隐藏是件好事,但并非总是可行。
-
由于不清楚您的处理程序在做什么,我无法解决您的具体情况。但我通常可以解决您的代码示例:使用 XAML 而不是 C# 创建视图模型实例,将视图模型分配给 XAML 中的
DataContext而不是 C#。考虑使用EventTriggers处理路由事件,例如PreviewMouseDown。 -
我尝试使用
EventTrigger方法,但它对我来说效果不佳,因为它不会更改标签背景,而是更改窗口的背景。有没有办法定位标签而不是窗口? (见编辑问题)@BionicCode -
只需将以下附加属性添加到每个
ColorAnimation:Storyboard.TargetName="Label"
标签: c# wpf mvvm data-binding code-behind