【问题标题】:C# WPF binding doesn't take data from PropertyC# WPF 绑定不从属性中获取数据
【发布时间】:2020-02-15 03:32:13
【问题描述】:

在我的 XAML 中,我正在执行以下操作

<Label Content="{Binding ElementName=Root, Path=UserData.Email, Mode=OneWay}" />

Root 元素是我的 Window 本身,UserData 是我的代码隐藏文件中的 get; private set; 自动属性,Email 属性是 get-only 并且是 string 类型。

UserData 对象在用户登录后被设置。但绑定没有从对象中获取值。我已经验证该对象确实包含正确的数据并且不是null。我在这里错过了什么?

【问题讨论】:

  • 您是否将标签的Datacontext 设置为Model
  • 不,我该怎么做?由于我之前没有使用过DataContext,所以我猜我先了解一下它是什么。
  • 首先你需要一个实现INotifyPropertyChanged的类,这个类将是你的Model View部分。然后您需要实例化该类的一个对象并将 DataContext 设置为该对象。基本上,它知道在哪里看。你真的需要找到一个好的教程。
  • 看来你也误解了MVVM-pattern的实现方式。您需要的是一个视图模型,其中包含您为视图(窗口)准备的数据。然后,您可以将该视图模型的属性绑定到视图上的控件属性。为了连接双方,您必须在其后面的代码中或直接在其 XAML 代码中设置窗口的 DataContext
  • private set去掉就行了

标签: c# wpf xaml binding


【解决方案1】:

我继续为此创建了一个 hello world 版本。这是xml。这应该只是在单击按钮时将横幅更改为文本框中的文本。我找不到一个超级简单的例子,所以我只做了一个。显然有更高级的方法可以做到这一点,但它应该可以构建一个简单的版本。

<Window x:Class="Hello_World.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Label Name="MyLabel" Content="{Binding MyLabel}" HorizontalAlignment="Left" Margin="58,37,0,0" VerticalAlignment="Top" Height="65" Width="423" FontSize="44"/>
        <TextBox Name="MyTextBox" HorizontalAlignment="Left" Height="28" Margin="163,162,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="163"/>
        <Button Content="Change Banner" HorizontalAlignment="Left" Margin="251,209,0,0" VerticalAlignment="Top" Width="109" Click="Button_Click"/>

    </Grid>
</Window>

接下来是实现INotifyPropertyChanged 接口的ModelView。请注意,您的属性必须是具有 getter、setter 和支持字段的公共属性。这允许您在设置属性时调用OnPropetyChanged() 方法。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Hello_World
{
    public class MainViewModel: INotifyPropertyChanged
    {


        private string _myLabel;

        public string MyLabel
        {
            get { return _myLabel; }
            set
            {
                _myLabel = value;
                OnPropertyChanged(nameof(MyLabel));
            }
        }    

        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string propetyName)
        {
            if(PropertyChanged != null)
            PropertyChanged(this,new PropertyChangedEventArgs(propetyName));

        }

    }
}

最后是主窗口。在主构造函数中设置DataContext。注意我可以设置主网格的DataContext,它的所有子网格都将继承相同的DataContext。这将使您不必单独设置所有组件。

namespace Hello_World
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainViewModel MyViewModel;


        public MainWindow()
        {
            InitializeComponent();
            MyViewModel = new MainViewModel();

            // Here's where I'm setting the object to look at.
            DataContext = MyViewModel;

            // Now I don't need to access the textbox directly.
            MyViewModel.MyLabel = "Hello World";    
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Note: ICommand is a more advanced topic.
            MyViewModel.MyLabel = MyTextBox.Text;
        }
    }
}

【讨论】:

  • 感谢您的努力和解释。如果我可以提出一个小建议,我会在从您的 MyLabel 属性调用 OnPropertyChanged 时使用 nameof
猜你喜欢
  • 2011-04-04
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 2011-04-04
  • 2022-01-14
  • 1970-01-01
相关资源
最近更新 更多