WPF 数据绑定到第二个视图

Posted

技术标签:

【中文标题】WPF 数据绑定到第二个视图【英文标题】:WPF Databinding to second view 【发布时间】:2022-01-01 00:27:26 【问题描述】:

我在这个问题上花了一天多一点的时间,我绝对是无能的。 如果我单击按钮以显示它打开的第二个视图,但没有内容。 我什至得到了视图模型中的断点。 为此,我将所有内容简化为一个简单的文本框和文本块,它们关闭显示相同的数据,但它们没有。即使在输入框后,它们也不会显示任何内容,该块不会更新。 但是我尝试过的数据绑定不起作用。有人有想法吗?

提前致谢

我的第二个视图

<Window x:Class="AoE4_BO_Overlay.Views.EditorView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:AoE4_BO_Overlay.Views" xmlns:viewmodels="clr-namespace:AoE4_BO_Overlay.ViewModels" d:DataContext="d:DesignInstance Type=viewmodels:EditorViewModel"
    mc:Ignorable="d"
    Title="EditorView" Height="450" Width="800">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="auto" />
        <ColumnDefinition Width="20" />
        <ColumnDefinition Width="20" />
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition Height="20" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="auto" />
        <RowDefinition Height="20" />
    </Grid.RowDefinitions>
    <TextBlock Text="Binding Path=FirstName" Grid.Column="0" Grid.Row="2"/>
    <TextBox Text="Binding Path=FirstName , Mode=OneWay" Grid.Column="0" Grid.Row="1"/>
</Grid>

我的视图模型

    internal class EditorViewModel : Conductor<object>

    private string _firstName = "Tom";
    public EditorViewModel()
    
    

    public string FirstName
    
        get
        

            return _firstName;
        
        set
        
            _firstName = value;
            NotifyOfPropertyChange(() => FirstName);
        
    

我怎么称呼他们两个

        public void CreateBO_Click(object sender, RoutedEventArgs e)
    
        EditorView createBO = new EditorView();
        ActivateItemAsync(new EditorViewModel());
        createBO.Show();
    

添加信息

    public partial class EditorView : Window

    public EditorView()
    
        DataContext = new EditorViewModel();
        InitializeComponent();
    

【问题讨论】:

【参考方案1】:

您有两个不同的问题:

1.输入文本框不会更改绑定属性:

这是预期的,因为您明确使用 OneWay 绑定。 OneWay 绑定意味着属性更新用户界面,而不是相反。 所以更改 FirstName 应该会更新 TextBox,但更改 TextBox 不会更新 FirstName。

有趣的是,如果您只是省略 Mode = OneWay 部分,它应该可以工作 - 因为 TextBoxes 应该默认使用 TwoWay 绑定。我建议您将 TextBox 绑定明确定义为 Mode = TwoWay

2。您的视图使用空的 TextBlock / TextBox 进行初始化

这个更难确定,因为您没有向我们展示您设置 DataContext 的位置。当我在InitializeComponent() 之后而不是之前设置 DataContext 时,这通常会发生在我身上。您可以在绑定初始化之前设置 DataContext(作为 InizializeComponent() 的一部分),或者您必须在属性上引发 NotifyPropertyChanged 以在之后更新 UI。

如果这不是原因,您可能希望在输出控制台中启用 WPF 绑定错误 - 这通常可以让您很好地了解绑定失败的位置。 Visual Studio 有一个选项。它应该位于此处:

工具 -> 选项 -> 调试 -> 输出窗口 -> WPF 跟踪设置 -> 数据绑定 -> 全部

【讨论】:

首先,非常感谢您的回答。 非常感谢!我需要搜索一下,但我找到了。 “DataContext = 新的 EditorViewModel();”是我错过的那条线。 这听起来不对。您确定 EditorViewModel 的新实例是您想要的吗?通常的做法是在InitializeComponent();之前使用DataContext = this; 确定吗?不。我读了一点并尝试了有效的方法。我的解决方案产生了预期的结果。如果我用this 替换new EditorViewModel(),它就不再起作用了。我不知道它是否无能为力,但我在项目中使用了 Caliburn.Micro。只是为了获得更多信息,我将相关课程添加到帖子中。【参考方案2】:

我相信您在这里尝试的是在第一个视图中显示您的第二个视图 (EditorView)(而不是作为弹出窗口 - 如果您打算将其作为弹出窗口,请使用 WindowManager 而不是 @ 987654324@).

要实现这一点,您需要更改的一件事是确保您的第二个 View 是 UserControl 而不是 Window。

// EditorView.xaml.cs
public partial class EditorView : UserControl

// EditView.xaml
<UserControl x:Class="AoE4_BO_Overlay.Views.EditorView"

此外,由于您使用的是ActivateItemAsync,因此您需要确保您的 FirstView 包含名称为“ActiveItem”的 ContendControl。

// FirstView.xaml
<ContentControl x:Name="ActiveItem"/>

ActivateItemAsync 的调用将使用此控件加载您的第二个ViewModel (EditorViewModel) 的视图。有了这个,您现在可以使用ActivateItemAsync 方法来加载视图。

public async Task CreateBO_Click(object sender, RoutedEventArgs e)

   await ActivateItemAsync(new EditorViewModel());

请注意,ActivateItemAsync 方法支持异步调用,最好异步调用该方法。

需要注意的另一点是,如果您使用的是 Caliburn Micro,并且 View/ViewModel 存储在推荐的文件夹/命名空间结构中,则不需要显式指定 DataContext,如 OP 中所示。 Caliburn Micro 使用命名约定来关联适当的视图-视图模型对。更多相关信息可以在official documentation

中找到

【讨论】:

以上是关于WPF 数据绑定到第二个视图的主要内容,如果未能解决你的问题,请参考以下文章

WPF - 绑定到用户控件之间的列表框的选定项

从数组中删除 - 致命错误:索引超出范围 - SwiftUI 绑定

windows phoneCollectionViewSource的妙用

WPF绑定第二个ListBox与第一个ListBox中的选定项目相关

wpf 控件属性通过数据绑定到某个集合的某一个数据上。

WPF: WrapPanel 容器的数据绑定(动态生成控件遍历)