首页 > 解决方案 > WPF 文本框绑定问题 DataItem = null?

问题描述

我是 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')

在此处输入图像描述

标签: c#wpfdata-binding

解决方案


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

所以你应该_selectedConfig变成一个属性,把它的名字改成S 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>

推荐阅读