Привязка MVVM к пользовательскому элементу управления в Windows Phone

#mvvm #windows-phone

#mvvm #windows-phone

Вопрос:

У меня есть следующий простой пользовательский элемент управления, который я определил для приложения Windows Phone. XAML для элемента управления выглядит следующим образом :

 <UserControl x:Class="PhoneApp1.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
         d:DesignHeight="480"
         d:DesignWidth="480"
         DataContext="{Binding RelativeSource={RelativeSource Self}}">

<Grid x:Name="LayoutRoot">
    <TextBlock Text="{Binding MyLabel}" />
</Grid>
 

Кроме того, пользовательский элемент управления имеет свойство зависимости, которое выглядит следующим образом :

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

    public static readonly DependencyProperty MyLabelProperty =
        DependencyProperty.Register("MyLabel", typeof (string), typeof (MyControl), new PropertyMetadata(default(string)));

    public string MyLabel
    {
        get { return (string) GetValue(MyLabelProperty); }
        set { SetValue(MyLabelProperty, value); }
    }
}
 

Теперь дело в том, что когда я пытаюсь привязать его к созданной мной модели представления, ничего не происходит. Различные элементы кода следующие :

 public class MyControlViewModel : ViewModelBase
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value;
        RaisePropertyChanged(() => Name);}
    }
}
 

Просмотр объявления модели в App.xaml

 <Application.Resources>
    <PhoneApp1:MyControlViewModel x:Key="MCVM" />
</Application.Resources>
 

Объявление элемента управления MainPage.xaml

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <PhoneApp1:MyControl  x:Name="testControl" DataContext="{StaticResource MCVM}" MyLabel="{Binding Path=MyLabel}" />            
    </Grid>
 

Однако, если я попытаюсь привязать его к какому-либо другому элементу пользовательского интерфейса следующим образом, похоже, это работает?

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <PhoneApp1:MyControl  x:Name="testControl" MyLabel="{Binding ElementName=Button, Path=Content}" />
        <Button Click="Button_Click" x:Name="Button" Content="Click" />
    </Grid>
 

Я изо всех сил пытался заставить этот простой сценарий работать, и я думаю, что есть что-то глупое, чего мне не хватает?

Любая помощь будет с благодарностью

Комментарии:

1. Вы хотите отобразить myLabel. Текст в текстовом блоке или что?

Ответ №1:

(Это WPF; Я не уверен, что это не 100% аналог WP7 silverlight; я предоставляю более подробную информацию, чтобы помочь вам понять, что происходит, чтобы вы могли найти правильное решение, если мои два варианта недоступны)

По умолчанию привязки имеют корни в DataContext корневого элемента файла xaml (будь то Window или UserControl). Это означает, что

 <TextBlock Text="{Binding MyLabel}" />
 

попытка привязки к DataContext. Итак, по сути, свойство, с которым вы пытаетесь связать, является

MyControl.DataContext.myLabel

Вместо этого необходимо выполнить привязку к следующему:

MyControl.myLabel

Итак, вы должны переназначить привязку к элементу в визуальном дереве, с которым вы хотите связать, к MyControl классу. Вы можете сделать это несколькими способами…

 <TextBlock Text="{Binding MyLabel, 
                 RelativeSource={RelativeSource FindAncestor,
                                                AncestorType=UserControl}" />
 

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

 <UserControl x:Class="PhoneApp1.MyControl"
             x:Name="root"
             x:SnipAttributesBecauseThisIsAnExample="true">
    <TextBlock Text="{Binding MyLabel, ElementName=root}" />
</UserControl>
 

Дайте вашему UserControl имя, затем используйте ElementName для перебазирования привязки к корню визуального дерева.

Я опущу другие, более дурацкие способы достижения этой цели.