WPF数据绑定 - 绑定对象。在Obj。到UserControl

时间:2013-05-07 16:55:36

标签: wpf data-binding

我在MainWindow.xaml中有2个用户控件,它们是SidePannelDescription。我正在传递一个DictionaryModel对象。在DictionaryModel对象中有一个Words集合和另一个名为SidePannelModel的对象。在SidePannelModel中,有另一个Words集合和一个字符串属性。

DictionaryModel

public class DictionaryModel : INotifyPropertyChanged
{

    public event PropertyChangedEventHandler PropertyChanged;

    public SidePannelModel SideModel { get; set; }
    public IEnumerable<WordModel> Language2 { get; set; }

    public void ToggleLanguage()
    {
        var temp = this.Language2;
        this.Language2 = this.SideModel.Language1;
        this.SideModel.Language1 = temp;

        OnPropertyChanged("DictionaryChanged");
    }


    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

SidePannelModel

public class SidePannelModel
{
    public IEnumerable<WordModel> Language1 { get; set; }
    public string SearchWord { get; set; }
}

我将DictionaryModel传递给MainWindow.xaml.cs中的DataContext。

    public partial class MainWindow : Window
    {
        private DictionaryModel dictionary;

        public MainWindow()
        {
            InitializeComponent();
            dictionary = new DictionaryModel
            {
                    SideModel = new SidePannelModel {
                    SearchWord=null,
                    Language1 = new List<WordModel>() 
                    { 
                        new WordModel() { Word = "Test1" }
                        , new WordModel() { Word = "Test2" }
                        , new WordModel() { Word = "Test3" }
                        , new WordModel() { Word = "Test4" }
                        , new WordModel() { Word = "Test5" }
                        , new WordModel() { Word = "Test6" }
                        , new WordModel() { Word = "Test7" }
                        , new WordModel() { Word = "Test8" }
                        , new WordModel() { Word = "Test9" }
                        , new WordModel() { Word = "Test10" }

                    } as IEnumerable<WordModel>
                },


                Language2 = new List<WordModel>() 
                { 
                    new WordModel() { Word = "Test1" }
                    , new WordModel() { Word = "Test2" }
                    , new WordModel() { Word = "Test3" }
                    , new WordModel() { Word = "Test4" }
                    , new WordModel() { Word = "Test5" }
                    , new WordModel() { Word = "kkkkk" }
                    , new WordModel() { Word = "Test7" }
                    , new WordModel() { Word = "Test8" }
                    , new WordModel() { Word = "Test9" }
                    , new WordModel() { Word = "Test10" }

                } as IEnumerable<WordModel>,

            };

            this.DataContext = dictionary;
        }
     }

这就是我将WordsSidePannelModel的集合传递给ManiWindow.xaml

中的用户控制器的方法
<Window x:Class="ThaiDictionary.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sidePanel="clr-namespace:ThaiDictionary"
    Title="MainWindow"
    Height="619">
<Window.Resources>
    <Style TargetType="{x:Type ToggleButton}"
       x:Key="toggleButtonStyle">
        <Style.Triggers>
            <Trigger Property="IsChecked" Value="True">
                <Setter Property="Content" Value="Thai to English" />
            </Trigger>
            <Trigger Property="IsChecked" Value="False">
                <Setter Property="Content" Value="English to Thai" />
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid Margin="0,0,2,0">

    <DockPanel LastChildFill="True">
        <Menu IsMainMenu="True" DockPanel.Dock="Top">
            <MenuItem Header="_File" />
            <MenuItem Header="_Edit" />
            <MenuItem Header="_View" />
            <MenuItem Header="_Window" />
            <MenuItem Header="_Help" />
        </Menu>
        <StatusBar Height="22" DockPanel.Dock="Bottom"/>
        <sidePanel:SidePanel SideModel="{Binding SidePModel, Mode=TwoWay}" DockPanel.Dock="Left" MinWidth="200" MinHeight="540" Margin="5,5,5,1" Width="196"/>
        <DockPanel LastChildFill="True" DockPanel.Dock="Left">
            <ToggleButton IsChecked="False" DockPanel.Dock="Top"  HorizontalAlignment="Left" Height="30" Width="150" Style="{StaticResource toggleButtonStyle}" Checked="ToggleButton_Checked" Unchecked="ToggleButton_Unchecked">
            </ToggleButton>
            <sidePanel:Description DockPanel.Dock="Top" WordsList2="{Binding Language2, Mode=TwoWay}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
        </DockPanel>

    </DockPanel>

</Grid>

SideModelSidePannel.xaml.cs中定义。

    public partial class SidePanel : UserControl
{
    public static DependencyProperty SideModelProperty;


    static SidePanel()
    {
        SideModelProperty = DependencyProperty.Register("SideModel", typeof(SidePannelModel), typeof(SidePanel)); 
    }

    public SidePanel()
    {
        InitializeComponent();

    }


    public SidePannelModel SideModel 
    {
         get
        {
            return (SidePannelModel)GetValue(SideModelProperty);
        }
        set
        {
            SetValue(SideModelProperty, value);
        }
    }

}

SidePanel控制器未加载我期待的Word s。

SidePanel.xaml的适当部分如下所示。

<UserControl x:Class="ThaiDictionary.SidePanel"
         x:Name="SidePannelController"
         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:l="clr-namespace:ThaiDictionary"
         mc:Ignorable="d" MinHeight="300" MinWidth="300" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Azure">
<UserControl.Resources>

</UserControl.Resources>

<DockPanel LastChildFill="True" DataContext="{Binding SidePModel}">
    <l:SearchTextBox SearchEventTimeDelay="00:00:02.00"  Text="{Binding  ElementName= SidePannelController,  Path= SearchWord, Mode=TwoWay}" DockPanel.Dock="Top"  Search="SearchTextBox_Search" HorizontalAlignment="Stretch" Background="Bisque"/>
    <ListBox Name="LeftSidePnel1" ItemsSource="{Binding  ElementName= SidePannelController,  Path= Language1, Mode=TwoWay}" HorizontalAlignment="Stretch"
         VerticalAlignment="Stretch" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ItemTemplate="{DynamicResource WordTemplate}" MinHeight="266" Height="auto" >
        <ListBox.Resources>
            <DataTemplate x:Key="WordTemplate">
                <Label Content="{Binding Word}" HorizontalAlignment="Left" VerticalAlignment="Top" Width="auto"/>
            </DataTemplate>
        </ListBox.Resources>
    </ListBox>
</DockPanel>

但是当我运行项目时,我看不到加载到Sidepanel用户控件中的单词。这段代码有什么问题。我在这里找不到出路。你能给我一些快速的帮助。

编辑:

我遵循了命名惯例并更改了SidePannel.xaml.cs

绑定错误:

 System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=SidePanelController'. BindingExpression:Path=SearchWord; DataItem=null; target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=SidePanelController'. BindingExpression:Path=Language1; DataItem=null; target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')

我添加了完整的SidePanel.xaml,我已将ElementName更改为SidePannelController,就像在xaml文件中一样。但它仍然没有加载单词

新编辑:

    System.Windows.Data Information: 41 : BindingExpression path error: 'SearchWord' property not found for 'object' because data item is null.  This could happen because the data provider has not produced any data yet. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=SideModel.SearchWord; DataItem='SidePanel' (Name='SidePannelController'); target element is 'SearchTextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Information: 41 : BindingExpression path error: 'Language1' property not found for 'object' because data item is null.  This could happen because the data provider has not produced any data yet. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 20 : BindingExpression cannot retrieve value due to missing information. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Information: 21 : BindingExpression cannot retrieve value from null data item. This could happen when binding is detached or when binding to a Nullable type that has no value. BindingExpression:Path=SideModel.Language1; DataItem='SidePanel' (Name='SidePannelController'); target element is 'ListBox' (Name='LeftSidePnel1'); target property is 'ItemsSource' (type 'IEnumerable')

由于

2 个答案:

答案 0 :(得分:1)

Language1SearchWord不是UserControl上的属性,而是UserControl.SideModel属性中的属性。

因此,更改您的绑定以在SideModel属性中包含Path,以便它正确绑定到SidePannelController.SideModel.Language1(或SearchWord),如下所示:

ItemsSource="{Binding ElementName=SidePannelController, Path=SideModel.Language1}"

但是我怀疑你没有显示你的实际XAML,因为你的绑定错误说“找不到绑定源”,这意味着它找不到名为SidePannelController的元素在VisualTree中(因为ElementName指定了用于绑定的源)。

如果是这种情况,您可以尝试使用RelativeSource绑定来查找UserControl而不是ElementName

ItemsSource="{Binding Path=SideModel.Language1,
    RelativeSource={RelativeSource AncestorType={x:Type l:SidePanel}}"

答案 1 :(得分:-1)

我不知道DictionaryModel是什么。

也许是一个错字,但你可能在之前的MainWindow.xaml.cs中有额外的},

Language2 = new List<WordModel>()

这意味着Language2不是dictionary.SideModel的成员,而是集合的另一个独立元素(SideModel的兄弟属性?)

但是,在MainWindow.xaml中,您绑定到SideModel绑定的<2> 内部。由于Language2不是SideModel的子级,因此XAML无法解析绑定。