欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

WPF 因设置不期望的DataContext,导致的绑定异常

程序员文章站 2022-04-10 14:38:15
在MainWindow中,创建一个背景属性BrushTest,并将其绑定至界面 并在窗口中添加一个UserControl,同样添加一个BackgroundTest属性,并将其绑定至界面。 运行后,控制台输出绑定异常,背景设置并没有生效。 System.Windows.Data Error: 40 : ......

在mainwindow中,创建一个背景属性brushtest,并将其绑定至界面

 1 <window x:class="wpfapp8.mainwindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:wpfapp8"
 7         mc:ignorable="d"
 8         title="mainwindow" height="450" width="800" x:name="themainwindow">
 9     <grid>
10         <local:usercontrol1 backgroundtest="{binding brushtest}"/>
11     </grid>
12 </window>
 1     public partial class mainwindow : window
 2     {
 3         public mainwindow()
 4         {
 5             initializecomponent();
 6             brushtest = brushes.red;
 7             this.datacontext = this;
 8         }
10         public static readonly dependencyproperty brushtestproperty = dependencyproperty.register(
11             "brushtest", typeof(solidcolorbrush), typeof(mainwindow), new propertymetadata(default(solidcolorbrush)));
13         public solidcolorbrush brushtest
14         {
15             get { return (solidcolorbrush) getvalue(brushtestproperty); }
16             set { setvalue(brushtestproperty, value); }
17         }
18     }

并在窗口中添加一个usercontrol,同样添加一个backgroundtest属性,并将其绑定至界面。

 1 <usercontrol x:class="wpfapp8.usercontrol1"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              xmlns:local="clr-namespace:wpfapp8"
 7              mc:ignorable="d" 
 8              d:designheight="450" d:designwidth="800">
 9     <grid background="{binding backgroundtest}">
10     </grid>
11 </usercontrol>
 1     public partial class usercontrol1 : usercontrol
 2     {
 3         public usercontrol1()
 4         {
 5             initializecomponent();
 6             this.datacontext = this;
 7         }
 8         public static readonly dependencyproperty backgroundtestproperty = dependencyproperty.register(
 9             "backgroundtest", typeof(solidcolorbrush), typeof(usercontrol1), new propertymetadata(default(solidcolorbrush)));
10         public solidcolorbrush backgroundtest
11         {
12             get { return (solidcolorbrush) getvalue(backgroundtestproperty); }
13             set { setvalue(backgroundtestproperty, value); }
14         }
15     }

运行后,控制台输出绑定异常,背景设置并没有生效。

system.windows.data error: 40 : bindingexpression path error: 'brushtest' property not found on 'object' ''usercontrol1' (name='')'.

bindingexpression:path=brushtest; dataitem='usercontrol1' (name=''); target element is 'usercontrol1' (name=''); target property is 'backgroundtest' (type 'solidcolorbrush')

为何错了呢?

因为usercontrol设置了俩次datacontext,usercontrol1内部设置的上下文覆盖了主窗口设置的上下文。

窗口内<local:usercontrol1 backgroundtest="{binding brushtest}"/>绑定的值brushtest,在usercontrol下的上下文无法找到相关值,所以报错了

 

此类绑定异常,一不小心还是很容易出现的。

在窗口设置了datacontext时(自身或者viewmodel),子控件也设置datacontext。有趣的是,在xaml编辑时,使用reshaper链接到的是窗口所在的上下文属性。

所以,子控件设置datacontext时,需要关注下否有属性被引用绑定外界数据。

建议子控件减少datacontext的使用,以上可以通过指定数据源进行绑定。比如:

 1 <usercontrol x:class="wpfapp8.usercontrol1"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              xmlns:local="clr-namespace:wpfapp8"
 7              mc:ignorable="d" 
 8              d:designheight="450" d:designwidth="800" x:name="theusercontrol">
 9     <grid background="{binding elementname=theusercontrol,path=backgroundtest}">
10     </grid>
11 </usercontrol>