Привязка не работает для текстового поля в DataTemplate в ContentPresenter - PullRequest
0 голосов
/ 22 мая 2018

Мое намерение: Отображение окна сообщения с текстом, введенным в элементе управления " userdata " при нажатии кнопки " Показать имя " (с помощьюпривязка данных вместо прямого доступа к свойству Text элемента управления " userdata ").Я написал этот код для понимания концепции шаблона в WPF .

Проблема с приведенным ниже кодом: Привязка данных не происходит, как предполагалось.

ПРИМЕЧАНИЕ : Однако, если я удалю « ContentPresenter » и « DataTemplate », окружающие « userdata "контроль, привязка данных работает нормально.Будут полезны любые ссылки, чтобы этот код работал.

Mainwindow.xaml:

<StackPanel>
    <Button x:Name="openFile">
        <Button.Template>
            <ControlTemplate>
                <Grid Width="300" Height="150">
                    <Rectangle Fill="Aquamarine" RadiusX="20" RadiusY="20" />
                    <Ellipse Fill="Azure"></Ellipse>
                    <ContentPresenter>
                        <ContentPresenter.ContentTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Horizontal" Height="50">
                                    <TextBlock Text="Name" />
                                    <TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
                                    <Button Content="Show Name" Click="Button_Click"></Button>
                                </StackPanel>
                            </DataTemplate>
                        </ContentPresenter.ContentTemplate>
                    </ContentPresenter>
                </Grid>
            </ControlTemplate>
        </Button.Template>            
    </Button>
</StackPanel>

UserName.cs

public class UserName : INotifyPropertyChanged
{
    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            FirePropertyChange("Name");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void FirePropertyChange(string propertyName)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

MainWindow.xaml.cs:

UserName user = new UserName();
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = user;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {           

        MessageBox.Show(user.Name);
    }

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Привязка данных происходит не так, как задумано в ContentTemplate, потому что Content не установлен.Добавьте привязку контента <ContentPresenter Content="{Binding}">, а остальное будет работать

<ContentPresenter Content="{Binding}">
    <ContentPresenter.ContentTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Height="50">
                <TextBlock Text="Name" />
                <TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
                <Button Content="Show Name" Click="Button_Click"></Button>
            </StackPanel>
        </DataTemplate>
    </ContentPresenter.ContentTemplate>
</ContentPresenter>
0 голосов
/ 22 мая 2018

Это происходит потому, что DataTemplate является «оболочкой» вокруг содержимого кнопки (Button.Content) и использует это содержимое как собственный DataContext.Если Content не указан, DataContext из DataTemplate имеет значение null, и привязка не выполняется.

Для правильной работы кода необходимо указать свойство Button.Content (это должен быть экземпляр класса UserName).

Вы можете использовать DataContext кнопки в качестве содержимого кнопки (этот способ уродлив, как утка).):

<Button Content="{Binding RelativeSource={RelativeSource Self}, Path=DataContext}">
<Button.Template>
    <ControlTemplate TargetType="Button">
        <Grid Width="300" Height="150">
            <ContentPresenter>
                <ContentPresenter.ContentTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Height="50">
                            <TextBlock Text="Name" />
                            <TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
                            <Button Content="Show Name"></Button>
                        </StackPanel>
                    </DataTemplate>
                </ContentPresenter.ContentTemplate>
            </ContentPresenter>
        </Grid>
    </ControlTemplate>
</Button.Template>

Когда вы удаляете DataTemplate и ContentPresenter из дерева, тогда TextBox просто наследует DataContext родителя (экземпляр UserName), поэтому привязка работает правильно.

Лучшийпуть идет по шаблону MVVM.

DataContext окна:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public UserName User { get; } = new UserName();
}

Назначить контекст данных окна:

public MainWindow()
{
    InitializeComponent();
    this.DataContext = new MainWindowViewModel();
}

Привязать кнопку к пользователю:

<Button Content="{Binding User}">
    <Button.ContentTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal" Height="50">
                <TextBlock Text="Name" />
                <TextBox x:Name="userdata" Text="{Binding Name, Mode=TwoWay}" Margin="5" Width="100" />
                <Button Content="Show Name"></Button>
            </StackPanel>
        </DataTemplate>
    </Button.ContentTemplate>
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Grid Width="300" Height="150">
                <ContentPresenter/>
            </Grid>
        </ControlTemplate>
    </Button.Template>
</Button>
0 голосов
/ 22 мая 2018

Проблема была решена путем изменения определения XAML элемента управления userdata , как показано ниже:

<TextBox x:Name="userdata" Text="{Binding DataContext.Name, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=Button,Mode=FindAncestor}}" Margin="5" Width="100" />

При наличии вложенных шаблонов компилятор может не определитьправильный родитель.Следовательно, необходимо упомянуть относительный источник с типом предка и путь с * DataContext. * Bindingdata

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...