【问题标题】:WPF textbox binding issue DataItem = null?WPF 文本框绑定问题 DataItem = null?
【发布时间】:2023-04-06 01:46:01
【问题描述】:

我是 WPF 框架的新手。文本框的属性“文本”的数据绑定不起作用。不知道代码有没有问题?

我有一个名为“ConfigListBox”的列表框和一个名为“NameTextBox”的文本框。

<ListBox x:Name="ConfigListBox" Grid.Row="0" Loaded="ConfigListBox_OnLoaded">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="MyApp:Config">
            <WrapPanel>
                <CheckBox Margin="0, 0, 2, 0"/>
                <TextBlock Text="{Binding Name}" />
            </WrapPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

<TextBox Name="NameTextBox" Grid.Column="1" Grid.Row="0" Text="{Binding SelectedConfig.Name}"></TextBox>

Object _selectedConfig 是 ConfigListBox 的选中项的实例。 _selectedConfig 将在 ConfigListBox 处于选定索引更改事件时更新。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private List<Config> _configs = new List<Config>();

    private Config _selectedConfig;

    public Config SelectedConfig
    {
        get => _selectedConfig;
        set
        {
            _selectedConfig = value;
            OnPropertyChanged();
        }
    }

    public MainWindow()
    {
        InitializeComponent();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Config 类实现了 INotifyPropertyChanged 接口。

class Config : INotifyPropertyChanged
{
    public string Name { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

找到数据上下文元素:? DataItem=null?,详细日志:

System.Windows.Data Warning: 67 : BindingExpression (hash=55056607): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=55056607): Found data context element: <null> (OK)
System.Windows.Data Warning: 74 :     Lookup name _selectedConfig:  queried TextBox (hash=14620943)
System.Windows.Data Warning: 67 : BindingExpression (hash=55056607): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=55056607): Found data context element: <null> (OK)
System.Windows.Data Warning: 74 :     Lookup name _selectedConfig:  queried TextBox (hash=14620943)
System.Windows.Data Warning: 67 : BindingExpression (hash=55056607): Resolving source 
System.Windows.Data Warning: 70 : BindingExpression (hash=55056607): Found data context element: <null> (OK)
System.Windows.Data Warning: 74 :     Lookup name _selectedConfig:  queried TextBox (hash=14620943)
System.Windows.Data Warning: 67 : BindingExpression (hash=55056607): Resolving source  (last chance)
System.Windows.Data Warning: 70 : BindingExpression (hash=55056607): Found data context element: <null> (OK)
System.Windows.Data Warning: 74 :     Lookup name _selectedConfig:  queried TextBox (hash=14620943)
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=_selectedConfig'. BindingExpression:Path=Name; DataItem=null; target element is 'TextBox' (Name='NameTextBox'); target property is 'Text' (type 'String')

【问题讨论】:

  • Name 属性不使用OnPropertyChanged
  • 对不起@styx,我没听懂你。你的意思是 _selectedConfig = ConfigListBox.SelectedItem as Config;不会触发 Config 对象中定义的属性更改事件?
  • 请看here
  • 谢谢@styx。试过你的文章,不行。但我发现有人在其他问题中提到了名称范围。

标签: c# wpf data-binding


【解决方案1】:

您的示例中没有名为_selectedConfig元素。确实有一个具有该名称的字段,但您不能绑定到字段,只能绑定到公共属性。

所以你应该把_selectedConfig 变成一个属性并且把它的名字改成SelectedConfig。

您还需要在要动态设置其属性的对象上实现INotifyPropertyChanged,在这种情况下为MainWindow:试试这个:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
    }

    private Config _selectedConfig;
    public Config SelectedConfig
    {
        get { return _selectedConfig; }
        set { _selectedConfig = value; OnPropertyChanged(); }
    }

    private void ConfigListBox_OnLoaded(object sender, RoutedEventArgs e)
    {
        _configs = ConfigHelper.ReadConfig();

        ConfigListBox.ItemsSource = _configs;

        ConfigListBox.SelectionChanged += ConfigListBoxOnSelectionChanged;
    }

    private void ConfigListBoxOnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        SelectedConfig = ConfigListBox.SelectedItem as Config;
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

XAML:

<ListBox x:Name="ConfigListBox" Grid.Row="0" Loaded="ConfigListBox_OnLoaded">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="MyApp:Config">
            <WrapPanel>
                <CheckBox Margin="0, 0, 2, 0"/>
                <TextBlock Text="{Binding Name}" />
            </WrapPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

<TextBox Name="NameTextBox" Text="{Binding SelectedConfig.Name}"></TextBox>

【讨论】:

  • 感谢您的帮助。我已经通过在 MainWindow 类中实现 INotifyPropertyChanged 尝试了您的解决方案。不幸的是,不适合我。
  • 什么不起作用?您真的将SelectedConfig property 设置为新值吗?如果您在正确的类中实现INotifyPropertyChanged,这确实有效。
  • 我已经在描述中发布了我的新代码。我添加了一个按钮来随机更改 SelectedConfig 的值,ConfigListBox 中的项目有效,但在文本框中失败。
  • “文本框失败”是什么意思?什么代码不起作用?您没有在示例中的某处设置 SelectedConfig 属性。
  • 我添加了一个按钮单击事件来动态设置 SelectedConfig 的名称,我看到 Listbox 中项目的值发生了变化。我希望 TextBox 的 text 属性也会被更改。
猜你喜欢
  • 2010-12-20
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多