gpt4 book ai didi

wpf - 调试 : Why a data-bound section breaks off when DataContext is reapplied?

转载 作者:行者123 更新时间:2023-12-01 15:37:33 25 4
gpt4 key购买 nike

2010年06月12日更新
将精华提炼成较小的 sample - 此处提供解决方案 http://db.tt/v6r45a4

现在看来是与选项卡控件相关的问题:当重新应用数据上下文(单击按钮)时,似乎一切都按预期进行。绑定(bind)会刷新,但事件选项卡上的所有绑定(bind)都会被破坏。

您可以通过选择任何选项卡并单击按钮来验证这一点,您会看到该选项卡上的控件失效。添加了一堆日志记录语句,这就是我的 friend 得出这个概要和他的修复方法的方式 [也在选项卡控件上设置 DataContext="{Binding}"]

但我们仍然不确定为什么会这样......

TabControl Data Context now set to ReproTabItemBug.MainViewModel
TabPage [LeftTabPage] Data Context now set to ReproTabItemBug.LeftViewModel
System.Windows.Data Error: 40 : BindingExpression path error: 'MiddleProp' property not found on 'object' ''MainViewModel' (HashCode=50608417)'. BindingExpression:Path=MiddleProp; DataItem='MainViewModel' (HashCode=50608417); target element is 'TextBox' (Name='MiddleTabTextbox'); target property is 'Text' (type 'String')
TabPage [MiddleTabPage] Data Context now set to ReproTabItemBug.MiddleViewModel
Middle tab textbox text changed to 634272638824920423
TabPage [RightTabPage] Data Context now set to ReproTabItemBug.RightViewModel
Middle tab textbox text changed to

上一篇文章(免责声明:前面有很长的帖子......拿你的爆米花。我已经花了一天的大部分时间......)

我的 ViewModel 由三个 POCO subViewModel 组成。每个 subVieModel 都具有在上述 3 个部分中绑定(bind)的属性。每个 subViewModel 都公开为标准的 .net 只读属性(无 INotifyPropertyChanged)

我的 View 有 3 个部分。每个部分都有一个像这样的 DataContext setter..

...
<TabItem x:Name="_tabPageForVM2" DataContext="{Binding PropReturningSubVM2}">
<!-- followed by UI Items that are data-bound to props inside this sub-viewmodel -->
</TabItem>
...

总结一下

<MainView> <!--DataContext set programmmatically to an Instance Of MainViewModel) -->
<Control DataContext="{Binding PropReturningSubVM1}" >.. Section1 .. </Control>
<Control DataContext="{Binding PropReturningSubVM2}" >.. Section2 .. </Control>
<Control DataContext="{Binding PropReturningSubVM3}" >.. Section3 .. </Control>
</MainView>

现在这是令人费解的一点。在正常启动时,我创建了一个 MainViewModel 实例(将 subview 模型传递给它的构造函数)。监 window 口中的属性证实了这一点。

    Trace.WriteLine("Before setting datacontext");
mainView.DataContext = null;
mainView.DataContext = mainViewModel;
//mainView.Refresh();
Trace.WriteLine("After setting datacontext");

一切正常。现在由于我无法控制的原因,出现了 UI 被关闭但 View 仍驻留在内存中的情况。因此,为了在下次显示时清除它,我创建了我的 View 模型的新实例并重新应用数据上下文(通过调用与以前相同的初始化例程)但是,当执行 DataContext=mainViewModel 集时,我在输出窗口中看到一堆绑定(bind)错误。有趣的是,只有一个标签页( subview 模型)内的绑定(bind)被破坏了。其他 2 个 subview 模型正常运行 - 没有绑定(bind)错误。

System.Windows.Data Error: 40 : BindingExpression path error: 'RphGaugeMaxScale' property not found on 'object' ''MainViewModel' (HashCode=38546056)'. BindingExpression:Path=RphGaugeMaxScale; DataItem='MainViewModel' (HashCode=38546056); target element is 'Gauge' (Name='GaugeControl'); target property is 'MaxValue' (type 'Double')
System.Windows.Data Error: 40 : BindingExpression path error: 'RphGaugeMaxScale' property not found on 'object' ''MainViewModel' (HashCode=38546056)'. BindingExpression:Path=RphGaugeMaxScale; DataItem='MainViewModel' (HashCode=38546056); target element is 'Gauge' (Name='GaugeControl'); target property is 'MajorTickCount' (type 'Int32')
...

属性存在于 SubViewModel2 上,但查找使用的是 MainViewModel。

接下来,我在 MainView 上添加了一个刷新方法(在重新应用 DataContext 后调用)来执行此操作

    _tabPageForVM2.DataContext = null;
_tabPageForVM2.DataContext = mainVM.PropReturningSubVM2;

这解决了问题。

让我困惑的是

  • subVM2 有什么特别之处?如果它在第一次分配 DataContext 时有效,为什么它会在第二次时中断?
  • 我将 tabPage 的 header 设置为 {Binding} 以检查它绑定(bind)到什么,它显示“FullTypeNameOfSubVM2”,这表明正在设置标签页的 DataContext 属性。那么为什么绑定(bind)会被破坏?

最佳答案

您可以下载Snoop或其他向您显示可视化树的工具,您会看到 TabItem 的内容实际上不是此 TabItem 的可视子项,而是 TabControl 的可视化子项。

alt text

所以 TabItem 是 TabItem 内容的逻辑子项,而 TabControl 是 TabItem 内容的可视子项。 DataContext 应该继承自逻辑父级,但在我看来它是随机继承自 TabItem 或 TabControl。

我建议的最佳解决方案是将绑定(bind)移动到内容,如下所示:

<TabItem x:Name="LeftTabPage" Header="LeftModel">
<StackPanel Orientation="Horizontal" DataContext="{Binding Left}">
<my:Gauge x:Name="gauge" Height="200" Width="200" Value="{Binding LeftProp}"/>
<Viewbox Height="200" Width="200" >
<my:Gauge x:Name="scaledGauge" Value="{Binding LeftProp}"/>
</Viewbox>
</StackPanel>
</TabItem>

<TabItem x:Name="MiddleTabPage" Header="{Binding}">
<TextBox x:Name="MiddleTabTextbox" DataContext="{Binding Middle}" Text="{Binding MiddleProp}" />
</TabItem>

<TabItem x:Name="RightTabPage" Header="RightModel">
<TextBox DataContext="{Binding Right}" Text="{Binding RightProp}"/>
</TabItem>

我想我明白了。我会尽力解释。

如果第二个选项卡处于事件状态(例如),则 MiddleTabTextbox 是 MiddleTabPage 的逻辑子项并且是 MyTabControl 的可视子项(它有 2 个不同的父项和 2 个不同的 DataContext)。第一个选项卡未激活,它只有逻辑子项 - StackPanel。当您单击按钮时,DataContext 发生变化。 StackPanel 没问题——它只有一个父级。但是 MiddleTabTextbox 应该做什么呢?它应该从可视父级还是逻辑父级获取 DataContext?从逻辑父级获取上下文似乎是合乎逻辑的:)我解释了这种行为,但是 MiddleTabTextbox 从视觉子级获取它,即 MyTabControl。因此,不是获取 MiddleViewModel,而是获取带有一堆绑定(bind)错误的 MainViewModel。我不知道为什么 WPF 从视觉父类而不是逻辑父类继承 DataContext。

关于wpf - 调试 : Why a data-bound section breaks off when DataContext is reapplied?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4331424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com