Метро: почему не работает привязка из XAML к свойству, определенному в коде? - PullRequest
0 голосов
/ 26 декабря 2011

Я пытаюсь слегка адаптировать пример приложения в стиле Metro в Windows, привязав текст заголовка к свойству, определенному в коде, но не могу заставить его работать.Читая сообщение в блоге под названием Привязка из XAML к свойству, определенному в выделенном коде , я пробую «Решение 1».

Вот мой исходный код XAML (упрощенно):

<UserControl x:Class="... .MainPage" x:Name="UserControlSelf"
    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"
    d:DesignHeight="768" d:DesignWidth="1366">

    <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}">
        <Grid.RowDefinitions>
            <RowDefinition Height="140"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <Grid x:Name="TitlePanel">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Button x:Name="BackButton" Click="BackButton_Click" Style="{StaticResource BackButtonStyle}"/>
            <TextBlock x:Name="PageTitle" Text="{Binding ElementName=UserControlSelf, Path=Title}" Style="{StaticResource TitleStyle}" Grid.Column="1"/>
        </Grid>
    </Grid>
</UserControl>

А вот мой код (в упрощенном виде):

public partial class MainPage
{
    private string _title;

    public MainPage()
    {
        _title = "Test";
        InitializeComponent();
    }

    public string Title
    {
        get
        {
            return _title;
        }
    }

    //...
}

Я установил точку останова на строке return _title; в получателе свойства Title.Когда я отлаживаю приложение, я вижу кнопку «Назад», но элемент управления текстового блока заголовка пуст (без текста) и точка останова не срабатывает:

Screenshot of the modified Metro-style app running, showing the back button, but no title

Я установил точку остановав автоматически сгенерированном коде C # для файла XAML и проверил, что UserControlSelf идентичен this в InitializeComponent().

Как связать Text элемента управления текстового блока заголовка с Title свойство определено в code-behind?

Ответы [ 4 ]

1 голос
/ 30 января 2013

Я не использовал Metro, но в WPF это не сработает, поскольку Title должно быть свойством зависимости. Измените свой код так:

public partial class MainPage
{


    public static readonly DependencyProperty TitleProperty;
    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    static MainPage()
    {
        TitleProperty= DependencyProperty.Register(
            "Title",
            typeof(string),
            typeof(MainPage));
    }

    public MainPage()
    {
        InitializeComponent();
        Title = "Test";
    }
}

Это застало меня вчера, это так легко забыть.

1 голос
/ 27 декабря 2011

Я наконец-то смог заставить его работать. Вместо того, чтобы возиться с ElementName и Path, я просто устанавливаю DataContext экземпляра MainPage для объекта , отличного от MainPage instance , который имеет свойство Title. Затем я изменил атрибут Text текстового блока заголовка на {Binding Title}.

Для объекта контекста данных нет необходимости реализовывать Windows.UI.Xaml.Data.INotifyPropertyChanged; однако при этом привязка автоматически ведет себя как привязка «в одну сторону».

Первоначально я пытался установить this.DataContext = this;, но, как я выяснил, , который не работает . Если я установлю его в POCO или просмотрю экземпляра модели, то привязка будет установлена.

Было бы интересно узнать, почему this.DataContext = this; ошибочен, но, по крайней мере, теперь я могу продолжить.

1 голос
/ 26 декабря 2011

Не могу протестировать приложение Metro прямо сейчас, но, возможно, вам следует реализовать INotifyPropertyChanged, чтобы привязка могла работать.

В вашем коде позади:

public event PropertyChangedEventHandler PropertyChanged;

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

public string Title
{
    get
    {
        return this._title;
    }

    set
    {
        if (this._title != value)
        {
            this._title = value;
            NotifyPropertyChanged("Title");
        }
    }
}

Также изменить

 _title = "Test";

до

 this.Title = "Test";
0 голосов
/ 13 января 2012

Этот метод всегда работает для меня

Text="{Binding ElementName=LayoutRoot, Path=Parent.Title}"

Предполагается, что именем дочернего элемента пользовательского элемента управления является «LayoutRoot», которое по умолчанию.

...