[英]How to Bind a DataContext to ViewModel inside window's DataContext?
我目前的视图如下所示:
<Window>
<DockPanel>
<Menu>
...
</Menu>
<StackPanel>
<Grid>
...
</Grid>
<Separator>
<Grid>
<Frame Source="ADifferentView.xaml" DataContext="{Binding ADifferentViewModel}">
<Frame...>
<Frame...>
</Grid>
</StackPanel>
</DockPanel>
</Window>
ViewModel 声明为:
public ResultsViewModel ADifferentViewModel{ get; set; }
并在构造函数中初始化。
ADifferentViewModel 是 Window 的 ViewModel 中的一个变量(已正确链接并正常工作)。 但是,框架与该变量的绑定似乎没有链接。
我的直觉表明这是由于需要获取 Window 的上下文。 我试过了:
DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=ADifferentViewModel}"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}, Path=ADifferentViewModel}"
然而,这些都不起作用。 我还尝试将 Window 更改为 DockPanel、StackPanel 和 Grid,但均无济于事。
任何建议将不胜感激,希望这足够清楚。 请询问您是否需要任何详细信息
由于某种原因,似乎Frame
的 DataContext 没有落入其内容中。但是,您可以从Frame
的LoadCompleted
事件中受益,像这样手动分配DataContext
:
.xaml
<Frame
x:Name="MyFrame"
LoadCompleted="MyFrame_OnLoadCompleted"
Source="ADifferentView.xaml" DataContext="{Binding ADifferentViewModel}"/>
.xaml.cs
private void MyFrame_OnLoadCompleted(object sender, NavigationEventArgs e)
{
if (MyFrame.Content is FrameworkElement content)
content.DataContext = MyFrame.DataContext;
}
您的解释和演示代码不足以回答您的问题。 我将向您展示一些绑定示例。
我希望这足以让您了解问题的原因。
例一。
设置 DataContext 并使用 TextBox 检查其值。
using System.Windows;
namespace Core2022.SO.HarryAdams
{
public partial class DataContextBindingWindow : Window
{
private readonly MainViewModel viewModel;
public DataContextBindingWindow()
{
InitializeComponent();
viewModel = new MainViewModel();
viewModel.ADifferentViewModel = new ResultsViewModel();
viewModel.ADifferentViewModel.Number = 12345678;
DataContext = viewModel;
}
}
public class ResultsViewModel
{
public int Number { get; set; }
}
public class MainViewModel
{
public ResultsViewModel? ADifferentViewModel { get; set; }
}
}
<Window x:Class="Core2022.SO.HarryAdams.DataContextBindingWindow"
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:Core2022.SO.HarryAdams"
mc:Ignorable="d"
Title="DataContextBindingWindow" Height="450" Width="800">
<StackPanel>
<Frame x:Name="frame" Height="100" DataContext="{Binding ADifferentViewModel}"/>
<TextBlock Text="{Binding DataContext.Number, ElementName=frame}"/>
</StackPanel>
</Window>
在此示例中,您可以看到 DataContext 正确绑定并显示正确的值。
第二个例子。
由于 DataContext 绑定工作正常,我假设您的意思是 DataContext 不是 Frame,而是 Page «ADifferentView»。
<Page x:Class="Core2022.SO.HarryAdams.ADifferentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Core2022.SO.HarryAdams"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="ADifferentView">
<Grid Background="LightSkyBlue">
<TextBlock Text="{Binding Number}"/>
</Grid>
</Page>
<Frame x:Name="frame" Height="100" DataContext="{Binding ADifferentViewModel}"
Source="/SO/HarryAdams/ADifferentView.xaml"/>
在此示例中,页面文本框收到一个锚定错误。 原因是 Page 用于表示 Frame.Content 属性。 由于此属性中未设置任何内容,因此页面数据上下文没有绑定 object。
同时,即使将 FindAncestor 类型显式绑定到 Frame 或 Window 也不能解决问题:
<Page x:Class="Core2022.SO.HarryAdams.ADifferentView"
DataContext="{Binding DataContext,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Frame}}}"
第三个例子。
在导航事件中将 Page DataContext 绑定到 object。
<StackPanel>
<Frame x:Name="frame" Height="100" DataContext="{Binding ADifferentViewModel}"
Source="/SO/HarryAdams/ADifferentView.xaml"
Navigated="OnNavigated"/>
<TextBlock Text="{Binding DataContext.Number, ElementName=frame}"/>
</StackPanel>
<x:Code>
<![CDATA[
private void OnNavigated(object sender, NavigationEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
FrameworkElement child = (FrameworkElement)e.Content;
child.SetBinding(DataContextProperty, new Binding("DataContext") { Source = element});
}
]]>
</x:Code>
</Window>
第四个例子。
此示例对于 WPF 页面更为典型。
他们要么创建自己的 DataContext,要么从 App 获取。
<Application.Resources>
<harryadams:MainViewModel x:Key="mainVM">
<harryadams:MainViewModel.ADifferentViewModel>
<harryadams:ResultsViewModel Number="1234567"/>
</harryadams:MainViewModel.ADifferentViewModel>
</harryadams:MainViewModel>
</Application.Resources>
<Page x:Class="Core2022.SO.HarryAdams.ADifferentView"
DataContext="{Binding ADifferentViewModel, Source={StaticResource mainVM}}"
第五例。
这个例子是比较典型的 WPF+MVVM 页面。 在这种情况下,锚点 object 在 Frame Content 中传递,页面类型在 DataTemplate 中指定:
<StackPanel>
<Frame x:Name="frame" Height="100" Content="{Binding ADifferentViewModel}">
<Frame.ContentTemplate>
<DataTemplate>
<local:ADifferentView/>
</DataTemplate>
</Frame.ContentTemplate>
</Frame>
<TextBlock Text="{Binding Content.Number, ElementName=frame}"/>
</StackPanel>
</Window>
您还可以使用默认数据模板:
<Window.Resources>
<DataTemplate DataType="{x:Type local:ResultsViewModel}">
<local:ADifferentView/>
</DataTemplate>
</Window.Resources>
<StackPanel>
<Frame x:Name="frame" Height="100" Content="{Binding ADifferentViewModel}"/>
<TextBlock Text="{Binding Content.Number, ElementName=frame}"/>
</StackPanel>
</Window>
第六个例子。
Frame+Page 经常用在错误的地方。
在绝大多数情况下,应改用 UserControl。 在这种情况下,对于大多数元素,所有绑定和传递 DataContext 开始以典型方式工作。
<UserControl x:Class="Core2022.SO.HarryAdams.ADifferentView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Core2022.SO.HarryAdams"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid Background="LightSkyBlue">
<TextBlock Text="{Binding Number}"/>
</Grid>
</UserControl>
<Window x:Class="Core2022.SO.HarryAdams.DataContextBindingWindow"
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:Core2022.SO.HarryAdams"
mc:Ignorable="d"
Title="DataContextBindingWindow" Height="450" Width="800">
<StackPanel>
<local:ADifferentView x:Name="frame" Height="100" DataContext="{Binding ADifferentViewModel}"/>
<TextBlock Text="{Binding DataContext.Number, ElementName=frame}"/>
</StackPanel>
</Window>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.