2012-07-04 26 views
1

这可能不是一个火箭科学问题,所以原谅我是一个新手! 我有一个UserControl用于设置一个人的名字(简单的测试目的)。UserControl具有传播到内部控制的绑定

PersonNameControl.xaml:

<UserControl x:Class="BindingPropagationTest.Controls.PersonNameControl" 
      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" 
      mc:Ignorable="d" Width="120" Height="23" Margin="0,0,0,0" 
      > 
    <TextBox Name="TextBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
</UserControl> 

,正如你所看到的,它包含一个文本框是 “真正的” 文本框。后面的代码看起来像这样。

PersonNameControl.xaml.cs:一起

<Window x:Class="BindingPropagationTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:my="clr-namespace:BindingPropagationTest.Controls" 
     xmlns:items="clr-namespace:BindingPropagationTest.ComboBoxItems" 
     Title="Testing binding in UserControl" 
     Width="179" Height="310"> 
    <Canvas Height="241" Width="144"> 

     <Label Canvas.Left="11" Canvas.Top="10" Content="Name" Height="28" Padding="0" /> 
     <my:PersonNameControl x:Name="nameControl" 
       Width="120" Height="23" 
       HorizontalAlignment="Left" VerticalAlignment="Top" 
       PersonName="{Binding name}" 
       Canvas.Left="11" Canvas.Top="28" /> 

     <Label Canvas.Left="11" Canvas.Top="57" Content="Address" Height="28" Padding="0" /> 
     <TextBox Canvas.Left="11" Canvas.Top="75" Width="120" Text="{Binding address}"></TextBox> 

     <Label Canvas.Left="11" Canvas.Top="103" Content="Age" Height="28" Padding="0" /> 
     <TextBox Canvas.Left="11" Canvas.Top="122" Height="23" Name="textBox1" Width="120" Text="{Binding age}" /> 

     <ComboBox Canvas.Left="11" Canvas.Top="173" Height="23" 
       Name="comboBox1" Width="120" SelectionChanged="comboBox1_SelectionChanged"> 
      <items:PersonComboBoxItem age="41" name="Donald Knuth" address="18 Donut Street" Height="23" /> 
      <items:PersonComboBoxItem age="23" name="Vladimir Putin" address="15 Foo Street" Height="23" /> 
      <items:PersonComboBoxItem age="32" name="Mike Hammer" address="10 Downing Street" Height="23" /> 
     </ComboBox> 
    </Canvas> 
</Window> 

与一些正常的文本框,你可以看到:

using System.Windows.Controls; 
using System.Windows; 
using System.Diagnostics; 

namespace BindingPropagationTest.Controls 
{ 
    public partial class PersonNameControl : UserControl 
    { 
     public static DependencyProperty nameProperty 
      = DependencyProperty.Register("PersonName", typeof(string), typeof(PersonNameControl)); 

     public string PersonName 
     { 
      get 
      { 
       Debug.WriteLine("get PersonNameControl.PersonName = " + TextBox.Text); 
       return TextBox.Text; 
      } 

      set 
      { 
       Debug.WriteLine("set PersonNameControl.PersonName = " + value); 
       TextBox.Text = value; 
      } 
     } 

     public PersonNameControl() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

我使用用户控件在MainWindow.xaml。

在后面的代码,主窗口

MainWindow.xaml.cs:

using System.Windows; 
using System.Windows.Controls; 
using BindingPropagationTest.ComboBoxItems; 

namespace BindingPropagationTest 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = new Person(); 
     } 

     private void comboBox1_SelectionChanged 
      (object sender, SelectionChangedEventArgs e) 
     { 
      updateForm(); 
     } 

     private void updateForm() 
     { 
      var item = (PersonComboBoxItem)comboBox1.SelectedItem; 

      DataContext = new Person() 
      { age = item.age, name = item.name, address = item.address };   
     } 
    } 
} 

你看,我设置的DataContext的 “人”。

Person.cs:

namespace BindingPropagationTest 
{ 
    public class Person 
    { 
     public string name {get; set; } 
     public int age { get; set; } 
     public string address { get; set; } 
    } 
} 

,当你发现我发明了一种自己ComboBoxItem这样。 PersonComboBoxItem.cs:

using System.Windows.Controls; 
using System.Diagnostics; 

namespace BindingPropagationTest.ComboBoxItems 
{ 
    public class PersonComboBoxItem : ComboBoxItem 
    { 
     private string _name = ""; 
     public string name 
     { 
      get 
      { 
       return _name; 
      } 
      set 
      { 
       _name = value; 
       Content = _name; 
      } 
     } 

     public int age { get; set; } 
     public string address { get; set; } 

     public override string ToString() 
     { 
      Debug.WriteLine("name: " + name); 
      return name; 
     } 
    } 
} 

运行该应用程序为您提供了此窗口:

enter image description here

,并选择一个组合框项目给你:

enter image description here

和你可以看到,名字不会被填入。 为什么不?

+1

只是一个简单的问题,不应该'DependencyProperty'实际上被裹得像个'{返回(串)的GetValue(nameProperty)填充; }'和'set'类似吗? –

+1

是的,先生!此外:不要向这些getter和setter添加任何逻辑,因为只有在您从代码设置属性时才调用它们。如果从XAML设置属性,则直接调用SetValue()方法。如果你想添加调试代码或逻辑,你必须注册一些回调给依赖属性:'新的FrameworkPropertyMetadata(OnPropertyValueChangedCallback,OnCoerceValuePropertyCallback),OnValidateValuePropertyCallback);' – Batuu

回答

2

你就要成功了,你需要一些东西来改变

依赖属性的使用类似

public static DependencyProperty NameProperty = DependencyProperty.Register(
    "Name", 
    typeof(string), 
    typeof(PersonNameControl)); 

    public string Name 
    { 
     get 
     { 
      return (string)GetValue(NameProperty); 
     } 
     set 
     { 
      SetValue(NameProperty, value); 
     } 
    } 

还有所必需的依赖属性非常严格的约定。如果该属性名为Name,则必须将其称为“NameProperty”。此属性只是设置并获取依赖项属性。

您可以将它们绑定文本框的财产在用户控件一样

<UserControl x:Class="BindingPropagationTest.Controls.PersonNameControl" 
     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" 
     x:Name="UserControl" 
     mc:Ignorable="d" Width="120" Height="23" Margin="0,0,0,0" 
     > 
    <TextBox Text="{Binding ElementName=UserControl, Path=Name}" Name="TextBox" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> 
</UserControl> 

我加入了X:名称=“用户控件”指令在上面,你可以使用任何名字,只要它匹配在绑定

额外注意的ElementName你如何填充你的组合框

你可以在你的主窗口添加属性

private ObservableCollection<Person> _thePeople; 
    public ObservableCollection<Person> ThePeople 
    { 
     get 
     { 
      if (_thePeople == null) 
      { 
       List<Person> list = new List<Person>() 
       { 
        new Person() { name = "Bob" , address = "101 Main St." , age = 1000 }, 
        new Person() { name = "Jim" , address = "101 Main St." , age = 1000 }, 
        new Person() { name = "Mip" , address = "101 Main St." , age = 1000 }, 
       }; 
       _thePeople = new ObservableCollection<Person>(list); 
      } 
      return _thePeople; 
     } 
    } 

那么你可以添加到您的主窗口中的X:在用户控件使用的名称指示说

x:Name="TheMainWindow" 

然后,您可以使用一个DataTemplate在你的组合框如下

<ComboBox ItemsSource="{Binding ElementName=TheMainWindow, Path=ThePeople}" 
      Height="23" 
      Name="comboBox1" Width="120" > 
     <ComboBox.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding name}" /> 
        <TextBlock Text="{Binding address}" /> 
        <TextBlock Text="{Binding age}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ComboBox.ItemTemplate> 
    </ComboBox> 

因为的ObservableCollection是用在组合框后面的代码中,只要代码隐藏添加或删除“ThePeople”集合中的项目,就会自动添加或删除项目。只需拨打

ThePeople.Add(new Person()); 

和组合框会自动用一个新条目

+0

感谢您的帮助!我已经知道GetValue和SetValue,但我忘记使用它们了!我必须做的第二件事是通过使用x:Name =“UserContro”绑定到usercontrol,再次感谢您的帮助!那么,我不必在setter中设置Text ...当然 –

相关问题