WPF 数据绑定到第二个视图

WPF Databinding to second view

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

提前致谢

我的第二个视图

<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.在文本框中键入内容不会更改绑定 属性:

这是预料之中的,因为您明确使用了单向绑定。单向绑定意味着 属性 更新用户界面,但反之则不然。 所以更改 FirstName 应该会更新 TextBox,但更改 TextBox 不会更新 FirstName。

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

2。您的视图初始化为一个空的 TextBlock / TextBox

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

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

Tools -> Options -> Debugging -> Output Window -> WPF Trace Settings -> Data Binding -> All

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

要实现这一点,您需要更改的一件事是确保您的第二个视图是 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/ViewModels 存储在推荐的 folder/namespaces 结构中,则无需像 OP 中那样明确指定 DataContext。 Caliburn Micro 使用命名约定来关联适当的视图-视图模型对。有关更多信息,请参见 official documentation