C# WPF窗口未使用XAML中的绑定进行更新
有人能解释一下这是怎么回事吗?我是WPF新手,正在使用绑定将表单项目迁移到WPF。我使用的是AvalonDock,但我没有直接绑定到任何AvalonDock控件。这里有几段摘录。为了简洁起见,我删除了很多内容,但如果您需要查看其他内容,请告诉我 编辑:这两个StackPanel只是测试。。。试图弄明白这件事。C# WPF窗口未使用XAML中的绑定进行更新,c#,wpf,C#,Wpf,有人能解释一下这是怎么回事吗?我是WPF新手,正在使用绑定将表单项目迁移到WPF。我使用的是AvalonDock,但我没有直接绑定到任何AvalonDock控件。这里有几段摘录。为了简洁起见,我删除了很多内容,但如果您需要查看其他内容,请告诉我 编辑:这两个StackPanel只是测试。。。试图弄明白这件事。 EDIT2:我最终会尝试做MVVM;我只需要更好地处理绑定,这样我就知道如何构造它。 EDIT3:见文章底部 问:第一个StackPanel根本不更新,更不用说更改后的更新了。我已尝试在S
EDIT2:我最终会尝试做MVVM;我只需要更好地处理绑定,这样我就知道如何构造它。
EDIT3:见文章底部 问:第一个
StackPanel
根本不更新,更不用说更改后的更新了。我已尝试在StackPanel
、Grid
和TextBlock
中设置DataContext
。我做错了什么
问:当父网格在代码隐藏中绑定时,第二种方法可以正常工作,但只有在您看到它的地方绑定,而不是在MainWindow\u Loaded()
方法中绑定。这里有什么不同
我已经阅读了好几篇教程以及很多类似的问题,但是没有任何东西能帮助我理解这里的区别和我遗漏了什么
private void主窗口\u已加载(对象发送方,路由目标)
{
this.DataContext=this;
SelectedEntityViewModel=new ViewModel.EntityViewModel();
ImportEntityXML_单击(null,null);//跳过单击菜单
}
私有void importentyxml\u单击(对象发送方,路由目标)
{
//省略了OpenFileDialog和XmlReader的内容
xmlreader=新的xmlreader(dlg.FileName);
Add(xmlreader.ReadEntityFromXML());
SimulatedEntitySelection(Entities.ElementAt(0));//尚未为此构建任何UI内容
}
私有所有权选择(实体ent)
{
选择edentityviewmodel.ActiveEntity=ent;
gridTest.DataContext=SelectedEntityViewModel.ActiveEntity;
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
选择edentityviewmodel.ActiveEntity.Label=“测试”;
}
Entity
和EntityViewModel
实现INotifyPropertyChanged
,第二个StackPanel
可以正常工作。调用button\u Click()
的按钮仅用于测试绑定EntityViewModel
几乎只是通过ActiveEntity
属性包装Entity
,并帮助读取Entity
中的集合集合
EDIT3:
我也尝试了一些资源。下面是我如何创建ObjectDataProvider的:
它确实有效。您可能正在更新错误的viewmodel 在
DataContext
中定义viewmodel后,必须通过以下方式访问它:
private void button_Click(object sender, RoutedEventArgs e)
{
var myModel = (ViewModel.EntityViewModel)(yourStackPanelName.DataContext);
myModel.ActiveEntity.Label = "test";
}
第一个堆栈面板不工作,因为数据上下文是继承的。因此,一旦将网格的DataContext更改为
ActiveEntity
对象,第一个数据上下文中文本块上的绑定将把TextBlock的DataContext设置为当前DataContext上的ActiveEntity
,它将已经是ActiveEntity
(因此ActiveEntity.ActiveEntity
)然后尝试绑定到该属性上的Label属性,例如ActiveEntity.ActiveEntity.Label
在单击之前,您将该窗口的DataContext设置为“this”,我假设它不是ViewModel,而是隐藏的代码
如果您使用的是MVVM
你应该有这样的东西
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
SelectedEntityViewModel = new ViewModel.EntityViewModel();
this.DataContext = SelectedEntityViewModel;
ImportEntityXML_Click(null, null); //skips clicking the menus
}
或其他提供所有必要数据的ViewModel
您通常会有一个MainWindowView
和MainWindowViewModel
,至少这是惯例,并且通常您会在构造函数中设置一次窗口的datacontext(您可以在加载的处理程序中执行),在大多数情况下,不需要手动更改代码隐藏中任何框架元素的DataContext
编辑:示例代码:
MainWindow.xaml
<Window x:Class="SO27760357.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label" />
<TextBlock Text="{Binding ActiveEntity.Label}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label Again" />
<TextBlock Text="{Binding ActiveEntity.Label}" />
</StackPanel>
</StackPanel>
</Grid>
</Window>
MainWindowViewModel.cs(为简单起见,省略了INotifyPropertChanged)
EntityViewModel.cs(为简单起见,省略了INotifyPropertChanged)
如您所见,我正在将窗口的DataContext设置为MainViewModel,因此DataContext(所有绑定的根)是MainViewModel,每个文本块需要首先访问ActiveEntity
属性,然后才能访问标签
项目
另一个选项是,如果您提供给我们的主堆栈面板中的所有内容都将绑定到ActiveEntity,那么您可以更改该堆栈面板的DataContext,将其绑定到ActiveEntity
,因此其所有子代DataContext也将是该对象
<StackPanel Orientation="Vertical"
**DataContext="{Binding ActiveEntity}"**>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label" />
<TextBlock **Text="{Binding Label}"**/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label Again" />
<TextBlock **Text="{Binding Label}"** />
</StackPanel>
</StackPanel>
编辑2-建议
您应该尽可能避免按名称引用对象,并且尽可能少地使用代码隐藏中的逻辑(如果有)。对于大多数简单屏幕,除了DataContext的初始绑定之外,不需要在代码隐藏中使用任何内容(如果您没有创建+设置windows DataContext的窗口服务)哦,天哪……在试图让它工作的所有愤怒的阴霾中,我确实忘记了为第一个StackPanel设置这个。我不得不承认,他关于DataContext继承的说明确实为我澄清了整个问题。哦,天哪,你击中了我的头。谢谢!你指出了我在第一个StackPanel上的问题,但你确实指出了arify数据上下文的继承
public class MainWindowViewModel
{
public EntityViewModel ActiveEntity { get; set; }
}
public class EntityViewModel
{
public string Label { get; set; }
}
<StackPanel Orientation="Vertical"
**DataContext="{Binding ActiveEntity}"**>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label" />
<TextBlock **Text="{Binding Label}"**/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Label Again" />
<TextBlock **Text="{Binding Label}"** />
</StackPanel>
</StackPanel>