Привязка MVVM к пользовательскому элементу управления в Windows Phone - PullRequest
3 голосов
/ 01 ноября 2011

У меня есть следующий простой пользовательский элемент управления, который я определил для приложения 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 Ответ

5 голосов
/ 01 ноября 2011

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

По умолчанию привязки начинаются с корня 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, чтобы перебазировать вашу привязку к корню визуального дерева.

IЯ опущу другие, более дурацкие способы сделать это.

...