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