WPF绑定失败:双重绑定解决方案?

时间:2014-07-30 17:10:14

标签: c# wpf xaml binding

我有一个用户控件来设置串口。 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属性。我错过了什么?

1 个答案:

答案 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