2015-07-31 2 views
0

Я хочу реализовать привязку между несколькими свойствами. Является ли это возможным ?Привязка объекта к другому имуществу, принадлежащему пользовательскому управлению

У меня есть класс главного окна с именем «MainWindow», которому принадлежит свойство «InputText». Этот класс содержит пользовательский элемент управления MyUserControl. MyUserControl имеет текстовое поле, привязанное к свойству зависимостей «MyTextProperty»

Я хотел бы связать свойство «InputText» моего главного окна с свойством зависимостей «MyTextProperty» моего пользовательского элемента управления. Итак, если пользователь пишет текст, я хочу, чтобы свойства «InputText», «MyTextProperty», «MyText» были обновлены.

код управления

Пользователь:

using System; 
using System.Linq; 
using System.Windows; 
using System.Windows.Controls; 
using System.ComponentModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MyUserControl.xaml 
    /// </summary> 
    public partial class MyUserControl : UserControl 
    { 

     public string MyText 
     { 
      get { return (string)GetValue(MyTextProperty); } 
      set { SetValue(MyTextProperty, value); } 
     } 

     public static readonly DependencyProperty MyTextProperty = 
      DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(0)); 



     public MyUserControl() 
     { 
      this.DataContext = this; 
      InitializeComponent(); 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void NotifyPropertyChanged(string property) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); 
      } 
     } 

    } 
} 

WPF код пользовательского управления:

<UserControl x:Class="WpfApplication1.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" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="25 " d:DesignWidth="100" 
      Background="Black"> 
    <Grid> 
     <TextBox Height="20" Width="100" Text="{Binding MyText}"></TextBox> 
    </Grid> 
</UserControl> 

Главный код окна:

using System; 
using System.Linq; 
using System.Windows; 
using System.ComponentModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     private string inputText; 

     public string InputText 
     { 
      get { return inputText; } 
      set 
      { 
       inputText = value; 
       NotifyPropertyChanged("InputText"); 
      } 
     } 

     public MainWindow() 
     { 
      this.DataContext = this; 

      InitializeComponent(); 

     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void NotifyPropertyChanged(String property) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); 
      } 
     } 
    } 
} 

WPF основного кода окно:

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:myNS="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="80" Width="300"> 
    <Grid> 
     <StackPanel Orientation="Vertical"> 
      <myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl> 
      <Button Name="cmdValidation" Content="Validation" Height="20"></Button> 
     </StackPanel> 
    </Grid> 
</Window> 

Спасибо!

+1

Вы получаете сообщение об ошибке с кодом выше? Какая конкретная проблема связана с попыткой привязать эти свойства. – Michael

+0

Ваш UserControl должен наследовать 'DataContext'' MainWindow', поэтому почему бы не привязать свойство TextBox Text непосредственно к свойству 'InputText'? – user2697817

ответ

2

Если вы хотите Опубликованный код для работы с минимальными изменениями, как это возможно, тогда:

В MainWindow.xaml, изменить

MyText="{Binding InputText}" 

в

MyText="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=DataContext.InputText, Mode=TwoWay}" 

Вам нужно TwoWay, если вы хотите, чтобы UC обновил InputText.

Кроме того, в MyUserControl.xaml.cs в вашем аргументе DependencyProperty.Register у вас есть значение по умолчанию для PropertyMetadata, равное 0 для строки - измените его на что-то подходящее для строки - например, null или string.empty.

public static readonly DependencyProperty MyTextProperty = 
    DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new PropertyMetadata(null)); 

Если вы хотите, чтобы изменить код немного, вы могли бы сделать это более сложным в управлении пользователя, но проще, когда вы используете его:

Заставить свойства зависимостей, MyText, связать два пути по умолчанию

Stop установка DataContext в пользовательском элементе управления

Смените UC XAML текст привязки использовать относительный источник УНЦ

Я всегда нахожу код проще для понимания, поэтому здесь модифицированные версии файлов: MainWindow.xaml

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:myNS="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="180" Width="300"> 
    <Grid> 
     <StackPanel Orientation="Vertical"> 
      <TextBlock> 
       <Run Text="MainWindow.InputText: " /> 
       <Run Text="{Binding InputText}" /> 
      </TextBlock> 
      <TextBlock> 
       <Run Text="MyUserControl.MyText: " /> 
       <Run Text="{Binding ElementName=test, Path=MyText}" /> 
      </TextBlock> 
      <myNS:MyUserControl x:Name="test" MyText="{Binding InputText}"></myNS:MyUserControl> 
      <Button Name="cmdValidation" Content="Validation" Height="20"></Button> 
     </StackPanel> 
    </Grid> 
</Window> 

MainWindow.xaml.cs

using System; 
using System.Windows; 
using System.ComponentModel; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     private string inputText = "Initial Value"; 

     public string InputText 
     { 
      get { return inputText; } 
      set 
      { 
       inputText = value; 
       NotifyPropertyChanged("InputText"); 
      } 
     } 

     public MainWindow() 
     { 
      this.DataContext = this; 

      InitializeComponent(); 

     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     protected void NotifyPropertyChanged(String property) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(property)); 
      } 
     } 
    } 
} 

MyUserControl.xaml

<UserControl x:Class="WpfApplication1.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" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="25 " d:DesignWidth="100" 
      Background="Black"> 
    <Grid> 
     <TextBox Height="20" Width="100" Text="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=MyText, UpdateSourceTrigger=PropertyChanged}"></TextBox> 
    </Grid> 
</UserControl> 

MyUserControl.xaml.cs

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

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MyUserControl.xaml 
    /// </summary> 
    public partial class MyUserControl : UserControl 
    { 

     public string MyText 
     { 
      get { return (string)GetValue(MyTextProperty); } 
      set { SetValue(MyTextProperty, value); } 
     } 

     public static readonly DependencyProperty MyTextProperty = 
      DependencyProperty.Register("MyText", typeof(string), typeof(MyUserControl), new FrameworkPropertyMetadata(null) { BindsTwoWayByDefault = true }); 

     public MyUserControl() 
     { 
      InitializeComponent(); 
     } 
    } 
} 
1

Во-первых,

this.DataContext = this; 

Нет, просто нет. Вы переопределяете DataContextUserControl, установленный его родительским окном.

Для вашего UserControl приведите его x:Name и привяжите непосредственно к свойству зависимости.

<UserControl 
    ... 
    x:Name="usr"> 

    <TextBox Text="{Binding MyText, ElementName=usr}" ... /> 

После того, как вы сделали это, вы можете просто связать свой MyText свойство к DataContext в MainWindow.

<myNS:MyUserControl x:Name="test" MyText="{Binding InputText}" /> 
Смежные вопросы