我有一个简单的测试ViewModel我的MainWindow:
namespace MyApp.ViewModels
{
class MainWindowViewModel : ViewModelBase
{
public string Test { get; set; } = "TEST";
}
}
没有比这更简单的了。现在我给我的MainWindow知识,并将Test属性绑定到一个TextBox和一个自己的UserControl:
<Window x:Class="MyApp.MainWindow"
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:MyApp"
xmlns:uc="clr-namespace:MyApp.UserControls"
xmlns:vm="clr-namespace:MyApp.ViewModels"
mc:Ignorable="d"
Width="800"
Height="600">
<Window.DataContext>
<vm:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox HorizontalAlignment="Left"
Grid.Row="0"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"
Text="{Binding Test, PresentationTraceSources.TraceLevel=High}" />
<uc:TestUserControl Grid.Row="1" Test="{Binding Test, PresentationTraceSources.TraceLevel=High}" />
</Grid>
</Window>
还是很简单。
我的TestUserControl看起来像这样:
<UserControl x:Class="MyApp.UserControls.TestUserControl"
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:MyApp.UserControls"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox HorizontalAlignment="Left"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"
Text="{Binding Test, PresentationTraceSources.TraceLevel=High}" />
</Grid>
</UserControl>
namespace MyApp.UserControls
{
public partial class TestUserControl : UserControl
{
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test", typeof(string), typeof(TestUserControl),
new FrameworkPropertyMetadata((string)String.Empty));
public string Test
{
get { return (string)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public TestUserControl()
{
InitializeComponent();
}
}
}
我基本上结束了两个文本框,一个包裹在我的UserControl,另一个没有。
两个文本框都应该包含文本"TEST",但只有不是嵌入到UserControl中的文本框才包含.
当我像这样跳过ViewModel的绑定时:
<uc:TestUserControl Grid.Row="1" Test="TEST" />
文本框中显示文本,这表明用户控件没有问题。
这是调试输出:
System.Windows.Data Warning: 56 : Created BindingExpression (hash=52579650) for Binding (hash=50581426) BindingExpression:Path=Test; DataItem=null;
System.Windows.Data Warning: 58 : Path: 'Test'
System.Windows.Data Warning: 60 : BindingExpression (hash=52579650): Default mode resolved to TwoWay
System.Windows.Data Warning: 61 : BindingExpression (hash=52579650): Default update trigger resolved to LostFocus
System.Windows.Data Warning: 62 : BindingExpression (hash=52579650): Attach to System.Windows.Controls.TextBox.Text (hash=15537542)
System.Windows.Data Warning: 67 : BindingExpression (hash=52579650): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=52579650): Found data context element: TextBox (hash=15537542) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=52579650): Activate with root item MainWindowViewModel (hash=13189358)
System.Windows.Data Warning: 108 : BindingExpression (hash=52579650): At level 0 - for MainWindowViewModel.Test found accessor RuntimePropertyInfo(Test)
System.Windows.Data Warning: 104 : BindingExpression (hash=52579650): Replace item at level 0 with MainWindowViewModel (hash=13189358), using accessor RuntimePropertyInfo(Test)
System.Windows.Data Warning: 101 : BindingExpression (hash=52579650): GetValue at level 0 from MainWindowViewModel (hash=13189358) using RuntimePropertyInfo(Test): 'TEST'
System.Windows.Data Warning: 80 : BindingExpression (hash=52579650): TransferValue - got raw value 'TEST'
System.Windows.Data Warning: 89 : BindingExpression (hash=52579650): TransferValue - using final value 'TEST'
System.Windows.Data Warning: 56 : Created BindingExpression (hash=26543418) for Binding (hash=62601592) BindingExpression:Path=Test; DataItem=null;
System.Windows.Data Warning: 58 : Path: 'Test'
System.Windows.Data Warning: 60 : BindingExpression (hash=26543418): Default mode resolved to TwoWay
System.Windows.Data Warning: 61 : BindingExpression (hash=26543418): Default update trigger resolved to LostFocus
System.Windows.Data Warning: 62 : BindingExpression (hash=26543418): Attach to System.Windows.Controls.TextBox.Text (hash=21868813)
System.Windows.Data Warning: 67 : BindingExpression (hash=26543418): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=26543418): Found data context element: TextBox (hash=21868813) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=26543418): Activate with root item TestUserControl (hash=21522166)
System.Windows.Data Warning: 108 : BindingExpression (hash=26543418): At level 0 - for TestUserControl.Test found accessor DependencyProperty(Test)
System.Windows.Data Warning: 104 : BindingExpression (hash=26543418): Replace item at level 0 with TestUserControl (hash=21522166), using accessor DependencyProperty(Test)
System.Windows.Data Warning: 101 : BindingExpression (hash=26543418): GetValue at level 0 from TestUserControl (hash=21522166) using DependencyProperty(Test): ''
System.Windows.Data Warning: 80 : BindingExpression (hash=26543418): TransferValue - got raw value ''
System.Windows.Data Warning: 89 : BindingExpression (hash=26543418): TransferValue - using final value ''
System.Windows.Data Warning: 56 : Created BindingExpression (hash=3865173) for Binding (hash=22799085) BindingExpression:Path=Test; DataItem=null;
System.Windows.Data Warning: 58 : Path: 'Test'
System.Windows.Data Warning: 60 : BindingExpression (hash=3865173): Default mode resolved to OneWay
System.Windows.Data Warning: 61 : BindingExpression (hash=3865173): Default update trigger resolved to PropertyChanged
System.Windows.Data Warning: 62 : BindingExpression (hash=3865173): Attach to MyApp.UserControls.TestUserControl.Test (hash=21522166)
System.Windows.Data Warning: 67 : BindingExpression (hash=3865173): Resolving source
System.Windows.Data Warning: 70 : BindingExpression (hash=3865173): Found data context element: TestUserControl (hash=21522166) (OK)
System.Windows.Data Warning: 78 : BindingExpression (hash=3865173): Activate with root item TestUserControl (hash=21522166)
System.Windows.Data Warning: 107 : BindingExpression (hash=3865173): At level 0 using cached accessor for TestUserControl.Test: DependencyProperty(Test)
System.Windows.Data Warning: 104 : BindingExpression (hash=3865173): Replace item at level 0 with TestUserControl (hash=21522166), using accessor DependencyProperty(Test)
System.Windows.Data Warning: 101 : BindingExpression (hash=3865173): GetValue at level 0 from TestUserControl (hash=21522166) using DependencyProperty(Test): ''
System.Windows.Data Warning: 80 : BindingExpression (hash=3865173): TransferValue - got raw value ''
System.Windows.Data Warning: 89 : BindingExpression (hash=3865173): TransferValue - using final value ''
这个问题的原因是什么?如何解决?
不要更改UserControl DataContext -你正在破坏与Window DataContext的连接。相反,通过ElementName更改Text biding以引用Test属性。
<UserControl x:Class="MyApp.UserControls.TestUserControl"
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:MyApp.UserControls"
mc:Ignorable="d"
Name="userControl"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox HorizontalAlignment="Left"
TextWrapping="Wrap"
VerticalAlignment="Top"
Width="120"
Text="{Binding Test, ElementName=userControl, PresentationTraceSources.TraceLevel=High}" />
</Grid>
</UserControl>
注意,即使没有ElementName=userControl
的绑定工作,但它将直接连接到dataContext - MainWindowViewModel。测试而不是TestUserControl。测试属性。在这种情况下,设置属性而不绑定-<uc:TestUserControl Grid.Row="1" Test="TEST" />
-将无法工作。
也将TestProperty更改为双向属性:
public static readonly DependencyProperty TestProperty = DependencyProperty.Register
(
"Test",
typeof(string),
typeof(TestUserControl),
new FrameworkPropertyMetadata(String.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault)
);