【发布时间】:2020-05-26 13:55:29
【问题描述】:
我一直在尝试将我的 Player 对象与我的 UI 绑定。 如果教程是正确的,我不明白为什么它不应该工作。 我有我的主窗口,当按下按钮时,它会在 tabPage 内创建一个 UserControl。此用户控件包含我的播放器。在主窗口中,我会将播放器传递给用户控件。 这是我的主窗口:
public partial class MainWindow : INotifyPropertyChanged
{
public MainWindow()
{
DataContext = this;
InitializeComponent();
}
private void AddPlayerClick(Object sender, RoutedEventArgs e)
{
AddTabItem("New Player", new AddPlayer(new Player(1, "asd", "asd", new DateTime(1,2,3), "asd", "asd", "asd", "asd", true)));
}
public void AddTabItem(String name, UserControl userControl)
{
TabItem tab = new TabItem
{
Header = name
};
userControl.DataContext = userControl;
tab.Content = userControl;
TabControl.Items.Add(tab);
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
<Window x:Class="Tournament_App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Tournament_App"
mc:Ignorable="d"
Title="MainWindow" Height="1920" Width="1080">
<StackPanel>
<Menu>
<MenuItem Header="Players">
<MenuItem Header="Add Player" Click="AddPlayerClick"/>
</MenuItem>
</Menu>
</StackPanel>
</Window>
单击按钮时,会创建一个新选项卡并让玩家通过。 然后在 AddPlayer 用户控件中将其设置为具有公共 get/setter 的私有属性。
public partial class AddPlayer : UserControl, INotifyPropertyChanged
{
private Player _player;
public Player Player
{
get { return _player; }
set {
_player = value;
OnPropertyChanged();
}
}
public AddPlayer(Player player)
{
DataContext = Player;
InitializeComponent();
Player = player;
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] String propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
然后我将玩家的名字绑定到一个文本框。
<UserControl x:Class="Tournament_App.Views.AddPlayer"
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:local="clr-namespace:Tournament_App.Views"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" >
<StackPanel>
<Label Content="First Name" />
<TextBox Text="{Binding FirstName, Mode=TwoWay}"/>
</StackPanel>
据我所知,数据上下文是正确的。而且绑定名称都是正确的,所以我不明白为什么它不起作用。任何帮助将不胜感激。我相信我更改了太多 INotifyProperty,但我无法确定我需要它们的地方。您可能会说我对 Wpf 很陌生。
【问题讨论】:
-
您真的想在 Window 类和 UserControl 中包含所有逻辑吗?通常使用 wpf,您希望坚持使用 mvvm-pattern,其中您有一个单独的 ViewModel 类,该类用作 View 中的 DataContext(在您的情况下为 MainWindow)用于数据绑定。
-
哦,在您的 AddPlayer 构造函数中,先尝试初始化您的 Player 属性:
Player = player,然后再将其设置为 AddPlayer 的 DataContext。按照您现在的方式,您将null分配为 DataContext。 -
DataContext = player -
在 WPF 中有一条一般规则 - 如果它看起来很难,很有可能你做错了。并非总是如此,但 99% 的情况都适用,您的情况就是其中之一。首先,在 XAML 中设置数据上下文,以便编辑器可以帮助您进行类型推断(效果很好)。其次,使用 MVVM 模式,起初它看起来很臃肿,但它可以工作(尤其是在某些框架下)。根据这 2 条建议,您将正确添加选项卡项(您的版本有效,但不是您应该这样做),如果 DataContex 绑定在 XAML 中,您将不会遇到此问题。
标签: c# wpf data-binding datacontext