2015-03-16 3 views
1

Я создал UserControl для отображения гиперссылки в своем приложении.RelativeSource-Binding для UserControl

Разметка этого UserControl выглядит следующим образом:

<UserControl x:Class="MVVMExample.View.UserControls.ActionLink" 
      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> 
     <TextBlock Margin="5"> 
       <Hyperlink Command="{Binding LinkCommand}" CommandParameter="{Binding LinkCommandParameter}"> 
        <TextBlock Text="{Binding LinkText, UpdateSourceTrigger=PropertyChanged}"/> 
       </Hyperlink> 
     </TextBlock> 
    </Grid> 
</UserControl> 

DataContext этого UserControl находится в CodeBehind, который выглядит как:

public partial class ActionLink : UserControl, INotifyPropertyChanged 
{ 
    public static readonly DependencyProperty LinkTextProperty = DependencyProperty.Register(
     "LinkText", typeof (string), typeof (ActionLink), new PropertyMetadata(LinkTextChanged)); 

    public static readonly DependencyProperty LinkCommandParameterProperty = DependencyProperty.Register(
     "LinkCommandParameter", typeof (object), typeof (ActionLink), 
     new PropertyMetadata(LinkCommandParameterChanged)); 

    public static readonly DependencyProperty LinkCommandProperty = DependencyProperty.Register(
     "LinkCommand", typeof (ICommand), typeof (ActionLink), new PropertyMetadata(LinkCommandChanged)); 

    public ActionLink() 
    { 
     InitializeComponent(); 
    } 

    public object LinkCommandParameter 
    { 
     get { return GetValue(LinkCommandParameterProperty); } 
     set { SetValue(LinkCommandParameterProperty, value); } 
    } 

    public string LinkText 
    { 
     get { return (string) GetValue(LinkTextProperty); } 
     set 
     { 
      SetValue(LinkTextProperty, value); 
      OnPropertyChanged(); 
     } 
    } 

    public ICommand LinkCommand 
    { 
     get { return (ICommand) GetValue(LinkCommandProperty); } 
     set { SetValue(LinkCommandProperty, value); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private static void LinkTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((ActionLink) d).LinkText = (string) e.NewValue; 
    } 

    private static void LinkCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((ActionLink) d).LinkCommandParameter = e.NewValue; 
    } 

    private static void LinkCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     ((ActionLink) d).LinkCommand = (ICommand) e.NewValue; 
    } 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

Все работает отлично.

Теперь, если я хочу использовать этот UserControl с командной Binding я должен сделать следующее:

<userControls:ActionLink LinkText="View customers" LinkCommand="{Binding DataContext.ViewCustomersCommand, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"/> 

Если я использую Button вместо этого я не должен предусматривать, что RelativeSource. Есть ли возможность, что я также не должен предоставлять RelativeSource о свойствах связывания пользовательских созданных UserControl?

ответ

2

Когда вы пишете

<userControls:ActionLink LinkCommand="{Binding ViewCustomersCommand}"/> 

WPF пытается установить привязку данных к ViewCustomersCommand собственности в DataContext вашего UserControl, который, как правило, унаследованного от родительского элемента управления, а также содержит ссылку на какой-то вид модели объекта , Это не работает здесь, потому что вы явно установили DataContext в экземпляр UserControl.

Как только у вас есть свойства связывания (то есть свойства зависимостей) в вашем UserControl, вы не должны устанавливать его DataContext. Если вы это сделаете, вам всегда придется явно указывать объекты источника привязки, потому что DataContext больше не унаследован.

Так удалить

DataContext="{Binding RelativeSource={RelativeSource Self}}" 

установка из XAML вашего UserControl и установить RelativeSource во всех его внутренних переплетов:

<Hyperlink 
    Command="{Binding LinkCommand, 
       RelativeSource={RelativeSource AncestorType=UserControl}}" 
    CommandParameter="{Binding LinkCommandParameter, 
         RelativeSource={RelativeSource AncestorType=UserControl}}"> 
    <TextBlock 
     Text="{Binding LinkText, 
       RelativeSource={RelativeSource AncestorType=UserControl} 
       UpdateSourceTrigger=PropertyChanged}"/> 
</Hyperlink> 
Смежные вопросы