我有一个用户控件来设置串口。 XAML是这样的:
<UserControl x:Class="DSS.Communication.UI.ComPortUI"
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:utilUI="clr-namespace:DSS.Util.UI;assembly=DSS.Util"
xmlns:localUI="clr-namespace:DSS.Communication.UI"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<utilUI:DebugConverter x:Key="DebugConverter"/>
<localUI:BoolXIsOpenConverter x:Key="IsOpenConverter"/>
</UserControl.Resources>
<StackPanel>
<StackPanel>
<TextBlock Text="{Binding StringFormat='ComPortUI.DataContext: {0}',FallbackValue='ComPortUI.DataContext: Null'}"/>
<TextBlock Text="{Binding StringFormat='ComPortUI.TargetPort: {0}',FallbackValue='ComPortUI.TargetPort: Null',RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl},Path=TargetPort}"/>
<DockPanel>
<utilUI:IndicatorLight DockPanel.Dock="Right" Width="20" CurrentBrush="{Binding IsOpen,Converter={StaticResource IsOpenConverter}}"/>
<TextBlock DockPanel.Dock="Right" Text="{Binding PortName.FriendlyName}"/>
</DockPanel>
<StackPanel Orientation="Horizontal">
<ComboBox x:Name="UI_AvailablePorts_CB" SelectedItem="{Binding PortName, Converter={StaticResource DebugConverter}}" Width="150">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding SimpleName}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox x:Name="UI_Baudrate_CB" SelectedItem="{Binding BaudRate}" Width="150">
</ComboBox>
</StackPanel>
<Button x:Name="UI_RawComs_Btn" Click="UI_RawComs_Btn_Click" IsEnabled="{Binding IsOpen}">Monitor</Button>
</StackPanel>
</StackPanel>
后面代码的importaint位是:
public IComPort TargetPort
{
get { return (IComPort)GetValue(TargetPortProperty); }
set { SetValue(TargetPortProperty, value); }
}
// Using a DependencyProperty as the backing store for TargetPort. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetPortProperty =
DependencyProperty.Register("TargetPort", typeof(IComPort), typeof(ComPortUI), new PropertyMetadata(null,TargetPort_Changed));
public static void TargetPort_Changed(DependencyObject d,DependencyPropertyChangedEventArgs e)
{
System.Diagnostics.Debugger.Log(0, "TargetPort_Changed",String.Format("{0}->{1}\r\n",e.OldValue,e.NewValue==null?"null":e.NewValue));
ComPortUI ui = (ComPortUI)d;
和此:
public ComPortUI()
{
_isMonitoring = false;
InitializeComponent();
foreach (ComPortName cpn in ComPort.AvailablePorts)
UI_AvailablePorts_CB.Items.Add(cpn);
foreach (int br in BaudRates)
{
UI_Baudrate_CB.Items.Add(br);
}
Dispatcher.BeginInvoke(new Action(() =>
{
System.Diagnostics.Debugger.Log(0, "ComPortUI()", "DataContext Changed\r\n");
DataContext = TargetPort;
}), System.Windows.Threading.DispatcherPriority.ApplicationIdle);
}
ui.DataContext = e.NewValue;
}
现在,当我像这样使用控件时:
MainWindow.cs:
public partial class MainWindow : Window {
public MainWindow() {
DataContext = new ComPort();
InitializeComponent();
}
}
public class MainWindowContext {
public MainWindowContext() {
Port = new ComPort();
}
public ComPort Port {
get;
protected set;
}
}
MainWindow.xaml:
<Window x:Class="DSSUITest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dss.communication.ui="clr-namespace:DSS.Communication.UI;assembly=DSS.Communication"
xmlns:dss.util.ui="clr-namespace:DSS.Util.UI;assembly=DSS.Util"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<dss.communication.ui:ComPortUI TargetPort="{Binding}"/>
</StackPanel>
</Window>
一切都很好,但当我这样做时:
MainWindow.cs:
public partial class MainWindow : Window {
public MainWindow() {
DataContext = new MainWindowContext()
InitializeComponent();
}
}
public class MainWindowContext {
public MainWindowContext() {
Port = new ComPort();
}
public ComPort Port {
get;
protected set;
}
}
MainWindow.xaml:
<Window x:Class="DSSUITest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dss.communication.ui="clr-namespace:DSS.Communication.UI;assembly=DSS.Communication"
xmlns:dss.util.ui="clr-namespace:DSS.Util.UI;assembly=DSS.Util"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<dss.communication.ui:ComPortUI TargetPort="{Binding Port}"/>
</StackPanel>
</Window>
我收到了绑定错误,特别是:
System.Windows.Data Error: 40 : BindingExpression path error: 'Port' property not found on 'object' ''ComPort' (HashCode=40105335)'. BindingExpression:Path=Port; DataItem='ComPort' (HashCode=40105335); target element is 'ComPortUI' (Name=''); target property is 'TargetPort' (type 'IComPort')
这会导致TargetPort和随后的DataContext变为null,这可能会导致一些问题。
我对此非常困惑,因为TargetPort属性实际上已经设置了两次,第一次正确(从null到Binding),然后是第二次,当......我不知道#39;确切地知道会发生什么。它看起来像绑定在两个单独的东西上解决两次,首先是MainWindowContext,然后是MainWindowContext的Port属性。我错过了什么?
答案 0 :(得分:0)
中的绑定
{Binding Port}
<dss.communication.ui:ComPortUI TargetPort="{Binding Port}"/>
指的是 ComPortUI 对象的DataContext属性提供的对象的属性 Port 。
查看 ComPortUI 的构造函数。在那里,您将 ComPortUI 对象的DataContext设置为 IComPort 实例:
DataContext = TargetPort;
因此,错误消息正确地抱怨它无法找到存储在 DataContext 中的对象的 Port 属性(这是一个对象提取的IComPort)。
解决方案应该很简单:不要在 ComPortUI 类中设置 DataContext 。