2014-10-15 4 views
1

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

Смотрите этот пример: http://www.codeproject.com/Articles/42203/How-to-Implement-a-DependencyProperty

Вместо <local:MyUserControl Caption="My First Dependency Property Example" /> я хочу что-то вроде <local:MyUserControl Caption="{Binding MyCaption}" /> где MyCaption является строковое свойство в классе ViewModel DataContext. Тем не менее, всякий раз, когда я изменить значение MyCaption, это не отражается на пользовательском элементе управления ...

Я получил этот собственный кусок кода, где я проверить тот же принцип, но текст никогда не обновляется:

MainWindow.xaml.cs:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window, INotifyPropertyChanged 
    { 
     private string _MyFirstName; 
     public string MyFirstName 
     { 
      get 
      { 
       return _MyFirstName; 
      } 
      set 
      { 
       _MyFirstName = value; 
       RaisePropertyChanged("MyFirstName"); 
      } 
     } 

     public MainWindow() 
     { 
      InitializeComponent(); 
     } 

     private void RaisePropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      //this.Klaas.SetValue(NameControl.FirstNameProperty, "Mike"); 
      MyFirstName = "Mike"; 
     } 
    } 
} 

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:me="clr-namespace:WpfApplication1" 
     Title="MainWindow" Height="350" Width="525" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <me:NameControl x:Name="Klaas" FirstName="{Binding MyFirstName}" Grid.Row="0"/> 
     <Button Grid.Row="1" Click="Button_Click">Pick a name</Button> 
    </Grid> 
</Window> 

NameControl.xaml.cs

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for NameControl.xaml 
    /// </summary> 
    public partial class NameControl : UserControl 
    { 
     public static readonly DependencyProperty FirstNameProperty = DependencyProperty.Register(
      "FirstName", 
      typeof(string), 
      typeof(NameControl), 
      new PropertyMetadata("NoName", OnFirstNamePropertyChanged)); 

     public string FirstName 
     { 
      get 
      { 
       return (string)GetValue(FirstNameProperty); 
      } 
      set 
      { 
       SetValue(FirstNameProperty, value); 
      } 
     } 

     private static void OnFirstNamePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
     { 
      NameControl source = d as NameControl; 
      // Do something... 
     } 

     public NameControl() 
     { 
      InitializeComponent(); 
     } 
    } 
} 

NameControl.xaml

<UserControl x:Class="WpfApplication1.NameControl" 
     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="300" d:DesignWidth="300" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto"/> 
     <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 
    <TextBlock Grid.Column="0" Width="100" Text="{Binding FirstName}" /> 
    <TextBlock Grid.Column="1" Width="100" Text="{Binding LastName}" /> 
</Grid> 
</UserControl> 

ответ

2

Когда вы

<UserControl ... DataContext="{Binding RelativeSource={RelativeSource Self}}"> 

вы эффективно затирать DataContext, которые обычно передаются ваш контроль от визуального дерева и изменить привязки контекста для привязки в NameControl управления. Я хотел бы предложить, чтобы удалить, что и делать, что за связывание

<TextBlock ... Text="{Binding FirstName, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 
<TextBlock ... Text="{Binding LastName, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> 

или сделать его проще дать UserControl некоторое имя и использовать его для связывания в пределах вашего контроля

<UserControl... x:Name="myUserControl"> 
    <Grid> 
     <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="Auto"/> 
     <ColumnDefinition Width="Auto"/> 
     </Grid.ColumnDefinitions> 
     <TextBlock Grid.Column="0" Width="100" Text="{Binding FirstName, ElementName=myUserControl}" /> 
     <TextBlock Grid.Column="1" Width="100" Text="{Binding LastName, ElementName=myUserControl}" /> 
    </Grid> 
</UserControl> 
+1

Yesss, теперь это работает! Спасибо. Великобритания спасла мой день! –

0

Ok, поэтому я изменил код XAML на это:

Почему все это сложное RelativeSource Нужно найти материал FindAncestor ??? Это неинтуитивный ад!

+0

Ваше решение работает, потому что изменяются связывания контекста для это привязка, поэтому он не полагается на «DataContext». Проверьте мой ответ – dkozl

Смежные вопросы