wpf 有趣的 ContentControl 绑定
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12535122/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
interesting ContentControl binding
提问by KitWat
First off I should say I an a newbie programmer and all help is appreciated. I'm currently working on a wpf application in which I would like to have usercontrol that has a label and a contentcontrol which can be updated based on which button is selected from the welcome view. like so
首先,我应该说我是一个新手程序员,感谢所有帮助。我目前正在开发一个 wpf 应用程序,其中我希望用户控件具有标签和内容控件,可以根据从欢迎视图中选择的按钮进行更新。像这样
<Window x:Class="ContentControl.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:ContentControl.ViewModels"
xmlns:views="clr-namespace:ContentControl.Views"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type vm:ScreenViewModel}">
<views:ScreenView DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:WelcomeViewModel}">
<views:WelcomeView DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:MeetingRoomViewModel}">
<views:MeetingRoomView DataContext="{Binding}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:DashboardViewModel}">
<views:DashboardView />
</DataTemplate>
</Window.Resources>
<Grid>
<StackPanel>
<Label>This Is My Label</Label>
<ContentControl x:Name="MainPanel" Content="{Binding Path=Content}"
MinHeight="200"
MinWidth="200"
HorizontalContentAlignment="Left"
VerticalContentAlignment="Center"
Focusable="False">
</ContentControl>
</StackPanel>
</Grid>
</Window>
CODE BEHIND:
背后的代码:
public MainWindow()
{
InitializeComponent();
DataContext = this;
MainPanel.Content = new WelcomeView();
MainPanel.Content = this.MainPanel.Content;
}
}
Here is the WelcomeViewModel:
这是欢迎视图模型:
internal class WelcomeViewModel : BaseViewModel
{
private MainWindowViewModel _mainWindowVm;
private RelayCommand<string> _viewChangedCommand;
public ICommand ViewChangedCommand
{
get { return _viewChangedCommand ?? (_viewChangedCommand = new RelayCommand<string>(OnViewChanged)); }
}
public event EventHandler ViewChanged;
private void OnViewChanged(string view)
{
EventHandler handler = ViewChanged;
if (handler != null) handler(view, EventArgs.Empty);
}
public MainWindowViewModel MainWindowVm
{
get { return _mainWindowVm; }
set
{
_mainWindowVm = value;
OnPropertyChanged("MainViewModel");
}
}
public WelcomeViewModel()
{
MainWindowVm = new MainWindowViewModel();
ViewChanged += MainWindowVm.ViewChanged;
}
}
And lastly my welcome.xaml
最后是我的welcome.xaml
<UserControl x:Class="ContentControl.Views.WelcomeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:ContentControl.ViewModels"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<vm:WelcomeViewModel />
</UserControl.DataContext>
<Grid Background="red">
<Grid.RowDefinitions >
<RowDefinition Height="25*" />
<RowDefinition Height="50*"/>
<RowDefinition Height="25*"/>
</Grid.RowDefinitions>
<Rectangle Grid.Row="0" Fill="Green"/>
<DockPanel Grid.Row="1" HorizontalAlignment="Center" Background="White">
<Button Height="50" Width="50" Margin="5" Content="DASH" Command="{Binding ViewChangedCommand}" CommandParameter="Dashboard"/>
<Button Height="50" Width="50" Margin="5" Content="ROOM" Command="{Binding ViewChangedCommand}" CommandParameter="MeetingRoom"/>
<Button Height="50" Width="50" Margin="5" Content="SCREEN" Command="{Binding ViewChangedCommand}" CommandParameter="Screen" />
</DockPanel>
<Rectangle Grid.Row="2" Fill="Blue"/>
</Grid>
</UserControl>
So the issue is when the ViewChange Event is fired off it is seen in the MainWindowViewModel however when it uses the PropertyEventHandler(as seen below) the PropertyChanged is always null.
所以问题是当 ViewChange 事件被触发时,它会在 MainWindowViewModel 中看到,但是当它使用 PropertyEventHandler(如下所示)时,PropertyChanged 始终为空。
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
回答by Raúl Ota?o
Well, here you have some WPF, Bindings, and Mvvm mistakes... First, why do you do this:
好吧,这里有一些 WPF、绑定和 Mvvm 错误……首先,为什么要这样做:
MainPanel.Content = this.MainPanel.Content;
that is the same as:
这与:
MainPanel.Content = MainPanel.Content;
this line is unecesary.
这条线是不必要的。
Second why you said:
第二个为什么你说:
Content="{Binding Path=Content}"
but then you set in your code behind:
但是然后你在你的代码后面设置:
MainPanel.Content = new WelcomeView();
Here you may have a conceptual error: When you set a binding by default this binding will be done to the DataContext of the control itself (the UserControl in this case). Ok, to solve this and work with Mvvm, lets to keep the binding:
在这里,您可能会遇到一个概念性错误:默认情况下,当您设置绑定时,此绑定将针对控件本身的 DataContext(在本例中为 UserControl)。好的,为了解决这个问题并使用 Mvvm,让我们保持绑定:
Content="{Binding Path=Content}"
But now we need to set the UserControl datacontext:
但是现在我们需要设置 UserControl 数据上下文:
MainPanel.DataContext = new MainPanelViewModel();
And now we need to create a property in the MainPanelViewModel called Content. Inside this property you will set the content that you want to show in the ContentControl.Content. (In this case a WelcomeViewModel and anything you want)
现在我们需要在 MainPanelViewModel 中创建一个名为 Content 的属性。在此属性中,您将设置要在 ContentControl.Content 中显示的内容。(在这种情况下是 WelcomeViewModel 和任何你想要的)
Hope this answer help to you to start with wpf and mvvm. it is a great platform.
希望这个答案对您开始使用 wpf 和 mvvm 有所帮助。这是一个很棒的平台。
回答by Erti-Chris Eelmaa
Okay. Mistakes you could fix:
好的。您可以修复的错误:
- dont change MainPanel.Content in code-behind. It's supposed to be changed in ViewModel through binding.
- In your Window.Resources, note that you're setting DataContext to MainViewModel of WelcomeView, and in WelcomeView you want it to be WelcomeIewModel. It does not work like that. The DataCOntext=WelcomeViewModel is overriden by the Window.Resources
- why are you creating new MainViewmodel in WelcomeViewModel?
- PropertyChanged is null because you are not using it in the View(that specific MainiewMOdel instance). If you're gonna bind against it, the PropertyChanged will reciee new event-listener and wont be null anymore.
- 不要在代码隐藏中更改 MainPanel.Content。它应该通过绑定在 ViewModel 中更改。
- 在您的 Window.Resources 中,请注意您将 DataContext 设置为 WelcomeView 的 MainViewModel,而在 WelcomeView 中,您希望它是 WelcomeIewModel。它不是那样工作的。DataCONtext=WelcomeViewModel 被 Window.Resources 覆盖
- 为什么要在 WelcomeViewModel 中创建新的 MainViewmodel?
- PropertyChanged 为 null,因为您没有在 View(该特定 MainiewMODEl 实例)中使用它。如果您要绑定它,PropertyChanged 将接收新的事件侦听器并且不再为空。
Perhaps explain your problem a little better and I can give further information.
也许可以更好地解释您的问题,我可以提供更多信息。

