WPF 嵌套数据绑定到控件 - 为什么它不起作用

本文关键字:为什么 不起作用 控件 嵌套 数据绑定 WPF | 更新日期: 2023-09-27 18:31:04

我已经搜索了很多谷歌和stackoverflow,以找到我问题的答案,但没有任何运气。我找到了解决问题的方法。前任:

将数据绑定到嵌套属性?

但我已经知道解决方案。我想知道为什么 wpf 不支持控件上的嵌套/点数据绑定。

解决方案是将父控件的 DataContext 设置为父数据对象,在我的情况下,我的控制器/窗口数据上下文上的 ViewModel 属性。因此,我可以设置网格的数据上下文,如果我将 TextBox 绑定更改为仅使用 Name 属性,我的代码将起作用。

另一种解决方案是显式设置我的文本框上的 UpdateSourceTrigger,并将我的嵌套数据绑定保留在文本框控件上,如下所示。

但是为什么?为什么 WPF 不支持嵌套绑定,就像下面所做的那样,而不设置 UpdateSourceTrigger 显式?我想知道:)。

我有这个文本框控件:

<Window>
    <Grid>
        <StackPanel>
            <Label Content="Name" FontWeight="Bold"/>
            <TextBox x:Name="NameTextBox" Text="{Binding Path=CreateEditAssetViewModel.Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" Width="475" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalContentAlignment="Stretch" Margin="0, 5" />
        </StackPanel>
    </Grid>
</Window>

我的窗口数据上下文绑定如下:

var createEditWindow = new CreateEditWindow();
var createEditController = new CreateEditWindowController();
createEditWindow.DataContext = createEditController;
createEditWindow.Show();

我的控制器如下所示:

public class CreateEditWindowController : ViewModelBase, ICreateEditWindowController
{
    private ICreateEditWindowViewModel _createEditWindowViewModel;
    public ICreateEditWindowViewModel CreateEditAssetViewModel
    {
        get { return _createEditWindowViewModel; }
        set
        {
            if (_createEditWindowViewModel == value) return;
            _createEditWindowViewModel = value;
            OnPropertyChanged(nameof(CreateEditAssetViewModel));
        }
    }
}

具有文本框控件绑定到的 Name 属性的 My ViewModel 如下所示:

public class CreateEditWindowViewModel : ViewModelBase, ICreateEditWindowViewModel
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set
        {
            if (_name == value) return;
            _name = value;
            OnPropertyChanged(nameof(Name));
        }
    }
}

还有我的视图模型库:

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

WPF 嵌套数据绑定到控件 - 为什么它不起作用

这是 https://msdn.microsoft.com/en-us/library/ms752347%28v=vs.100%29.aspx

查看"提供视觉反馈"部分,它是一个触发器绑定属性,但他们使用了虚线属性

集合视图部分相同 子 -> 如何创建视图

他们在应用程序对象上使用虚线属性。

调试 GUI 时查看输出视图,如果 WPF 在数据上下文中找不到属性,它将抛出日志!

WPF 确实支持点属性,但是是的,您始终必须指定控件数据上下文。

我认为 wpf 确实支持嵌套/点分数据绑定。我已经在您提到的链接中发布了答案。哪里

<TextBox Text="{Binding Path=MyModel.MyCounter.CurrentNumber}"/>

绑定工作正常。不是在这里,但我做了很多嵌套属性需要绑定到某个控件属性的示例。事实上,WPF 必须支持这种类型的绑定,否则为单独的控件提供单独的 DataContext 将是一项非常困难的工作。

一些例子:

1.

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type iDP:DataRecordCellArea}},Path=Record.DataItem.IsParentRow}" Value="true">
 <Setter Property="IsEnabled" Value="False"/>

阿拉伯数字。

<CheckBox HorizontalAlignment="Center"
                          VerticalAlignment="Center"
                          Cursor="Arrow" 
                          IsChecked="{Binding Path=DataItem.IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type view:DeleteSubLocationsView}},Path=DataContext.ImportWizardViewModel.ContextObject.IsRQSReviewFieldChecked}">

嵌套绑定的工作原理示例

在 WPF 中必须注意的一件事是将属性设置为"依赖项属性"。这有助于通知值更改:

C#

    public static readonly DependencyProperty SelectedNodeProperty = DependencyProperty.Register(nameof(SelectedNode), typeof(FileSystemEntry), typeof(MainWindow));
    public FileSystemEntry SelectedNode
    {
        get => (FileSystemEntry)GetValue(SelectedNodeProperty);
        set => SetValue(SelectedNodeProperty, value);
    }

XAML:

<TextBox DataContext="{Binding ElementName=MainAppWindow,Path=SelectedNode}" Text="{Binding Name,Mode=OneWay}"/>
<TextBox Text="{Binding ElementName=MainAppWindow,Mode=OneWay,Path=SelectedNode.Name}"/>

现在,如果SelectedNode更改值,则将更新 UI。

我希望这有所帮助。