2012-04-15 110 views
3

我的绑定不起作用。我搜索了错误,但我不明白如何解决它在我的情况。绑定错误与ListView,UserControl,DependencyProperty,ObservableCollection,INotifyPropertyChanged

System.Windows.Data Error: 1 : Cannot create default converter to perform 'one-way' conversions between types 'MyApplication.MyUserControl' and 'MyApplication.Person'. Consider using Converter property of Binding. BindingExpression:Path=; DataItem='MyUserControl' (Name=''); target element is 'MyUserControl' (Name=''); target property is 'PersonInfo' (type 'Person')

System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='MyApplication.MyUserControl' BindingExpression:Path=; DataItem='MyUserControl' (Name=''); target element is 'MyUserControl' (Name=''); target property is 'PersonInfo' (type 'Person')

基本上它是一个ListView绑定到类Person的ObservableCollection。

MainWindow.xaml.cs

public partial class MainWindow : Window 
{ 
    public ObservableCollection<Person> PersonCollection { set; get; } 

    public MainWindow() 
    { 
     PersonCollection = new ObservableCollection<Person>(); 
     InitializeComponent(); 
     PersonCollection.Add(new Person() { Name = "Bob", Age = 20 }); 
    } 
} 

MainWindow.xaml

<Window DataContext="{Binding RelativeSource={RelativeSource Self}}" xmlns:self="clr-namespace:MyApplication" x:Class="MyApplication.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
<ListView ItemsSource="{Binding PersonCollection}"> 
    <ListView.ItemTemplate> 
     <DataTemplate> 
      <StackPanel> 
       <self:MyUserControl PersonInfo="{Binding}" /> 
      </StackPanel> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 
</Window> 

MyUserControl.xaml.cs

public partial class MyUserControl : UserControl 
{ 
    public static readonly DependencyProperty PersonProperty = DependencyProperty.Register("PersonInfo", typeof(Person), typeof(MyUserControl)); 

    public Person PersonInfo 
    { 
     get { return (Person)GetValue(PersonProperty); } 
     set { SetValue(PersonProperty, value); } 
    } 

    public MyUserControl() 
    { 
     InitializeComponent(); 
    } 
} 

MyUserControl.xaml

<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}" x:Class="MyApplication.MyUserControl" 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"> 
<TextBlock Text="{Binding PersonInfo.Name}" /> 
</UserControl> 

Person.cs

public class Person : INotifyPropertyChanged 
{ 
    public int Age { set; get; } 
    public string Name { set; get; } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String info) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(info)); 
    } 
} 

回答

3

我不明白为什么你会让它变得复杂。您可以轻松地绑定您的UserControl,而不需要修改其DataContext属性。

<UserControl x:Class="MyApplication.MyUserControl" 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"> 
    <TextBlock Text="{Binding Name}" /> 
</UserControl> 

然后将UserControl放置在DataTemplate中,无需显式绑定。它的DataContext将会包含一个Person对象。

<DataTemplate>  
    <StackPanel>  
     <self:MyUserControl />  
    </StackPanel>  
</DataTemplate>  
+0

你是完全正确的!感谢澄清。 – fanti 2012-04-15 17:18:56

1

更改您的用户控件XAML来

<UserControl x:Class="MyApplication.MyUserControl" 
      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"> 
    <TextBlock DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}" 
       Text="{Binding PersonInfo.Name}" /> 
</UserControl> 

这里是用的DataContext问题good explanation

+0

问题解决了!谢谢! – fanti 2012-04-15 17:04:12

+1

查看我添加的链接以供进一步调查。 – LPL 2012-04-15 17:09:48

2

虽然你能解决问题,你的整个绑定代码似乎是错误的我,所以我提出这个替代:

有一个基类的所有绑定源对象 - ObservableObject.cs

public abstract class ObservableObject : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
      handler(this, e); 
    } 

    protected void SetValue<T>(ref T field, T value, string propertyName) 
    { 
     if (!EqualityComparer<T>.Default.Equals(field, value)) 
     { 
      field = value; 
      this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

有你的主窗口视图模型 - MainWindowModel.cs

public class MainWindowModel : ObservableObject 
{ 
    private readonly ObservableCollection<Person> personCollection = new ObservableCollection<Person>() 
    { 
     new Person() { Name = "Bob", Age = 20 } 
    }; 

    public ObservableCollection<Person> PersonCollection 
    { 
     get { return this.personCollection; } 
    } 
} 

MainWindow.xaml.cs现在基本上是空的。

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
    } 
} 

MainWindow.xaml套的DataContext新MainWindowModel实例。

<Window x:Class="MyApplication.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:self="clr-namespace:MyApplication"> 
    <Window.DataContext> 
     <self:MainWindowModel/> 
    </Window.DataContext> 
    <ListView ItemsSource="{Binding PersonCollection}"> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <self:MyUserControl/> 
       </StackPanel> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
</Window> 

MyUserControl。xaml.cs也基本上是空的(仅包含自动生成的代码)。

public partial class MyUserControl : UserControl 
{ 
    public MyUserControl() 
    { 
     InitializeComponent(); 
    } 
} 

MyUserControl.xaml

<UserControl x:Class="MyApplication.MyUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <TextBlock Text="{Binding Name}"/> 
</UserControl> 

Person.cs

public class Person : ObservableObject 
{ 
    private int age; 
    private string name; 

    public int Age 
    { 
     get { return this.age; } 
     set { this.SetValue(ref this.age, value, "Age"); } 
    } 

    public string Name 
    { 
     get { return this.name; } 
     set { this.SetValue(ref this.name, value, "Name"); } 
    } 
} 
+0

非常好!感谢您改进我的代码并帮助我变得更好,非常感谢! – fanti 2012-04-15 17:54:26

相关问题