Свойство зависимости Silverlight snafu, что я делаю не так? - PullRequest
2 голосов
/ 10 августа 2010

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

Элемент управления представляет собой расширенное текстовое поле, которое поддерживает HTML, но не через свойство; Вы должны сделать что-то вроде этого:

var sHtml = "..."
ctrl.LoadHtml(sHtml)

и

var sHtml = ctrl.SaveHtml()

Пока все хорошо. Но я хочу установить HTML через привязку данных, поэтому я создал свойство зависимости под названием Html:

    public static readonly DependencyProperty HtmlProperty =
        DependencyProperty.Register(
            "Html",
            typeof(string),
            typeof(RichTextEditor),
            new PropertyMetadata(string.Empty, new PropertyChangedCallback(HtmlChangedCallback))
            );

    public string Html
    {
        get {return (string)GetValue(HtmlProperty);}

        set {SetValue(HtmlProperty, value);}
    }

    private static void HtmlChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //get the control
        var rte = (RichTextEditor)d;

        //got here, so load the html
        rte.TextBox.LoadHtml((string)e.NewValue);
    }

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

    private void rtb_ContentChanged(object sender, RichTextBoxEventArgs e)
    {
        //tell the html prop that it changed
        SetValue(HtmlProperty, rtb.SaveHtml());
    }

Но тогда это вызывает HtmlChangedCallback, и повторный вход вызывает проблемы. Итак, я попытался использовать флаг повторного входа, но это стало грязным, потому что последовательность событий сложнее, чем я ожидал, и в этот момент я решил, что, должно быть, что-то упустил, поэтому я спрашиваю здесь. Пожалуйста помоги! Заранее спасибо.

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

Ответы [ 2 ]

0 голосов
/ 10 августа 2010

Это небольшая классическая проблема, которая обычно решается простым логическим флагом.

private bool suppressHtmlChanged = false;

private static void HtmlChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{

    var rte = (RichTextEditor)d;

    if (!rte.suppressHtmlChanged)
        rte.TextBox.LoadHtml((string)e.NewValue);
}


private void rtb_ContentChanged(object sender, RichTextBoxEventArgs e)
{
    suppressHtmlChanged = true;
    SetValue(HtmlProperty, rtb.SaveHtml());
    suppressHtmlChanged = false;
}

В наши дни такие решения кажутся такими старомодными, не так ли, часто мы можем убедить себя, что такие «низкотехнологичные» решения не могут быть правильными, потому что они не «элегантны».

0 голосов
/ 10 августа 2010

Зачем вам нужно уведомить систему собственности?Вы пытаетесь обновить источник привязки данных?Элемент управления не должен реализовывать INotifyPropertyChanges;этот интерфейс должен быть реализован в классе, который предоставляет данные для привязки данных.

Что если вы пока игнорируете Save / LoadHtml и просто сохраняете HTML как строку?Работает ли он без проблем?

Вот пример, который отлично работает для меня

class MyControl
{
    public int Value
    {
        get
        {
            return (int)GetValue(ValueProperty);
        }

        set
        {
            SetValue(ValueProperty, value);
            Count.Text = value.ToString();
        }
    }

    public static readonly DependencyProperty ValueProperty =
        DependencyProperty.Register("Value",
            typeof(int),
            typeof(Vote),
            new PropertyMetadata(0, OnValueChanged));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((MyControl)d).Value = (int)e.NewValue;
    }

Счетчик - это элемент управления текстовым блоком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...