Что я делаю неправильно? Свойство зависимости внутри пользовательского элемента управления с привязкой данных - PullRequest
3 голосов
/ 18 марта 2012

(отредактировано для исправления синтаксической ошибки DP - проблема все еще сохраняется)

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

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

Если я делаю все это на странице без контроля пользователявсе работает правильно.Однако, как только я перемещаю его в пользовательский контроль, он начинает действовать странно.Начальное число 0 отображается при запуске, как и ожидалось, и когда я нажимаю кнопку, пересмотренный счет отображается при первом нажатии.Однако, если я снова нажму ту же кнопку, свойство зависимости будет обновлено, но значение не будет отображаться (метка станет пустой).Если я нажму на другую кнопку, то появится пересмотренный счетчик, но только для первого щелчка - все это очень странно, и я застрял!

Если я поставлю точку останова на метод TheCountProperty_Changed,Я могу убедиться, что значение свойства обновляется правильно ..

Вот XAML для моего пользовательского элемента управления:

<UserControl
x:Class="DPTest.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DPTest"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400"
x:Name="TestControl"
x:Uid="TestControl">

<Grid>
    <TextBlock x:Name="lblCount" HorizontalAlignment="Left" Margin="0,0,0,0" TextWrapping="Wrap" Text="{Binding Path=TheCount, ElementName=TestControl, Mode=OneWay}" VerticalAlignment="Top" FontSize="36"/>
    <Button x:Name="btnLess" Content="&lt;" HorizontalAlignment="Left" Margin="0,71,0,0" VerticalAlignment="Top" Width="75" Click="btnLess_Click" ClickMode="Press"/>
    <Button x:Name="btnMore" Content="&gt;" HorizontalAlignment="Left" Margin="91,71,0,0" VerticalAlignment="Top" Width="75" Click="btnMore_Click" ClickMode="Press"/>

</Grid>

И вот CS для него:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace DPTest
{
public sealed partial class UserControl1 : UserControl
{
    public static readonly DependencyProperty TheCountProperty = DependencyProperty.Register("TheCount", typeof(int), typeof(UserControl1), new PropertyMetadata(0, new PropertyChangedCallback(TheCountProperty_Changed)));

    public int TheCount
    {
        get { return (int)GetValue(TheCountProperty); }
        set { SetValue(TheCountProperty, value); }
    }
    private static void TheCountProperty_Changed(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {

    }

    public UserControl1()
    {
        this.InitializeComponent();
    }

    private void btnLess_Click(object sender, RoutedEventArgs e)
    {
        //lblCount.Text = (Convert.ToInt32(lblCount.Text) - 1).ToString();
        this.TheCount -= 1;
    }

    private void btnMore_Click(object sender, RoutedEventArgs e)
    {
        //lblCount.Text = (Convert.ToInt32(lblCount.Text) + 1).ToString();
        this.TheCount += 1;
    }
}
}

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

(РЕДАКТИРОВАТЬ) - сюжет утолщается!Хотел добавить, что я только что попробовал точно такой же синтаксис в стандартном приложении WPF, и все работает как положено.Так что я думаю, вопрос в том, нашел ли я ошибку в WinRT / XAML или синтаксис отличается на этой платформе?

(Правка № 2 извините за все правки, но я все еще пытаюсь это исправитьout!) Я начинаю верить, что это проблема с дисплеем или ошибка с кнопочным управлением.Я только что добавил дополнительную кнопку, но не связал ее с кодом события клика или чем-то еще - это просто кнопка, которая ничего не делает.Вот что интересно:

  • Если я запускаю тестовое приложение, нажимаю кнопку btnMore, затем значение TheCount увеличивается, а текстовый блок обновляется, как и ожидалось.Если затем я снова нажму ту же кнопку, значение TheCount будет увеличено, но значение Text для lblCount станет пустой строкой.
  • Если, однако, я запускаю тестовое приложение и нажимаю btnMore, затем нажимаю неиспользованную кнопку и сохраняюповторяя это, затем значение продолжает увеличиваться, и TextBlock будет продолжать обновляться - до тех пор, пока я не нажму btnMore два раза подряд, а нажму пустую кнопку (или просто наведу курсор на пустое текстовое поле или любой другой элемент пользовательского интерфейса).), тогда TextBlock продолжит отображать увеличивающийся номер.Когда я нажимаю btnMore более одного раза, значение lblCount становится пустой строкой.

Это очень странно ....

Ответы [ 3 ]

2 голосов
/ 18 марта 2012

Третий аргумент свойства DependencyProperty выглядит так, как будто он должен быть 'UserControl1', а не 'UserControl'.

После запуска Win 8 и пробного кода для себя я обнаружил ту же проблему, что и у вас.

Из этого я смог определить две вещи:

1) Ваше свойство зависимости было в основном правильным. Я мог наблюдать, как значение свойства увеличивалось и уменьшалось при нажатии кнопок. Это указывало на то, что проблема была в некотором роде проблемы обновления.

2) Перемещение кода из UserControl на главную страницу xaml (в моем тестовом приложении это была страница по умолчанию «Blank.xaml») позволило правильному обновлению номера.

Мне кажется, что есть какая-то ошибка обновления с бета-версией (ошибка .. 'Предварительный просмотр потребителя'), которую можно обойти, структурировав свое приложение немного по-другому.

1 голос
/ 19 марта 2012

Это похоже на проблему с синхронизацией в WinRT - я использовал конвертер, чтобы проверить, что получаю, и мне показалось, что значение int было установлено равным нулю.После того, как я изменил код, чтобы асинхронно вызывать обновления свойства - он начал нормально работать.

XAML:

<UserControl
    x:Class="DPTest.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DPTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400"
    x:Name="TestControl"
    x:Uid="TestControl">

    <Grid>
        <Grid.Resources>
            <local:IntToStringConverter
                x:Key="IntToStringConverter" />
        </Grid.Resources>
        <TextBlock
            x:Name="lblCount"
            HorizontalAlignment="Left"
            Margin="0,0,0,0"
            TextWrapping="Wrap"
            Text="{Binding Path=TheCount, Converter={StaticResource IntToStringConverter}, ElementName=TestControl, Mode=OneWay}"
            VerticalAlignment="Top"
            FontSize="36" />
        <Button
            x:Name="btnLess"
            Content="&lt;"
            HorizontalAlignment="Left"
            Margin="0,71,0,0"
            VerticalAlignment="Top"
            Width="75"
            Click="btnLess_Click"
            ClickMode="Release" />
        <Button
            x:Name="btnMore"
            Content="&gt;"
            HorizontalAlignment="Left"
            Margin="91,71,0,0"
            VerticalAlignment="Top"
            Width="75"
            Click="btnMore_Click"
            ClickMode="Release" />
    </Grid>
</UserControl>

Код позади:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace DPTest
{
    public sealed partial class UserControl1 : UserControl
    {
        public static readonly DependencyProperty TheCountProperty =
            DependencyProperty.Register(
                "TheCount",
                typeof(int),
                typeof(UserControl1),
                new PropertyMetadata(
                    0,
                    new PropertyChangedCallback(TheCountProperty_Changed)));

        public int TheCount
        {
            get { return (int)GetValue(TheCountProperty); }
            set { SetValue(TheCountProperty, value); }
        }

        private static void TheCountProperty_Changed(DependencyObject source, DependencyPropertyChangedEventArgs e)
        {

        }

        public UserControl1()
        {
            this.InitializeComponent();
        }

        private void btnLess_Click(object sender, RoutedEventArgs e)
        {
            //lblCount.Text = (Convert.ToInt32(lblCount.Text) - 1).ToString();
            this.Dispatcher.InvokeAsync(
                Windows.UI.Core.CoreDispatcherPriority.Low,
                (s, a) => this.TheCount -= 1,
                this,
                null);
        }

        private void btnMore_Click(object sender, RoutedEventArgs e)
        {
            //lblCount.Text = (Convert.ToInt32(lblCount.Text) + 1).ToString();
            this.Dispatcher.InvokeAsync(
                Windows.UI.Core.CoreDispatcherPriority.Low,
                (s, a) => this.TheCount += 1,
                this,
                null);
        }
    }

    public class IntToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return value.ToString();
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

}
0 голосов
/ 19 марта 2012

Я сделал нечто очень похожее, унаследовав от RichTextBox.

http://www.wpfsharp.com/2011/08/01/loading-a-richtextbox-from-an-rtf-file-using-binding-or-a-richtextfile-control/

Я вижу, что не сделал свое свойство зависимости доступным только для чтения (не уверен, имеет ли это значение)

Кроме того, я предполагаю, что вы намереваетесь заполнить это:

private static void TheCountProperty_Changed(DependencyObject source, DependencyPropertyChangedEventArgs e)
{

}
...