Проблема привязки текстового поля WPF DataItem = null? - PullRequest
0 голосов
/ 22 марта 2020

Я новичок в WPF Framework. Привязка данных для свойства «Текст» текстового поля не работает. Не уверен, что с кодом что-то не так?

У меня есть список с именем «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>

Объект _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')

enter image description here

1 Ответ

0 голосов
/ 23 марта 2020

В вашем примере нет элемента с именем _selectedConfig. Действительно, есть поле с таким именем, но вы не можете связать его с полями, только с публикацией c свойств.

Таким образом, вы должны превратить _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>
...