Модераторы: gambit, Kefir, Partizan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> userControl-> DepProp -> ContentPresenter 
:(
    Опции темы
makaka
Дата 1.8.2011, 22:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 25.10.2009

Репутация: нет
Всего: нет



Всем привет.

Создаю userControl
В нем - ContentPresenter
Создаю DependencyProperty для ContentPresenter.Content

В MainPage вставляю userControl
В его DependencyProperty вставляю TextBlock и даю ему имя

При запуске приложения вижу, что в объекте MainPage есть поле с названием TextBlock, но оно null
Хотя на экране все ок


Ниже код. Я ставлю в дебаггере точку останова на операции в методе Button_Click
четко видно что this.MyLabel равно null. Вылетает ArgumentNullException

Если присвоить имя созданному userControl или любому другому контролу - все ок.


Я думаю, что проблема где-то в реализации DependencyProperty - реализация необычная и дает много возможностей (по сути дает в Silverlight возможности WPF DependencyProperty)
Либо же это баг Silverlight

Вот здесь лежит архив с кодом проекта и сниппетом для DependencyProperty: iFolder

Помогите пожалуйста разобраться с проблемой


Код

<UserControl x:Class="TestApp.SomeContainer"
    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="300" d:DesignWidth="400">
    
    <Grid x:Name="LayoutRoot" Background="White">
        <ContentPresenter x:Name="MyCP"/>
    </Grid>
</UserControl>


Код

using System;
using System.Windows;
using System.Windows.Controls;

namespace TestApp {
    public partial class SomeContainer : UserControl {
        public SomeContainer() {
            InitializeComponent();

            MyContentChanged += new RoutedPropertyChangedEventHandler<FrameworkElement>(SomeContainer_MyContentChanged);

            //apply default values to the View
            this.SomeContainer_MyContentChanged(null, null);
        }

        #region Event handlers
        //bridge between two objects - DependencyProperty and ContentPresenter
        //This EH used when dependencyProperty changed from code
        void SomeContainer_MyContentChanged(object sender, RoutedPropertyChangedEventArgs<FrameworkElement> e) {
            this.MyCP.Content = this.MyContent;
        }
        #endregion Event handlers

        #region public FrameworkElement MyContent
        /// <summary>
        /// Gets or sets the value of MyContent dependency property.
        /// </summary>
        public FrameworkElement MyContent {
            get { return (FrameworkElement)GetValue(MyContentProperty); }
            set { SetValue(MyContentProperty, value); }
        }
        /// <summary>
        /// Identifies the MyContent dependency property.
        /// </summary>
        public static readonly DependencyProperty MyContentProperty =
            DependencyProperty.Register(
                "MyContent",
                typeof(FrameworkElement),
                typeof(SomeContainer),
                new PropertyMetadata(null, OnMyContentPropertyChanged));
        /// <summary>
        /// MyContentProperty property changed handler.
        /// </summary>
        /// <param name="d">SomeContainer that changed its MyContent.</param>
        /// <param name="e">Event arguments.</param>
        private static void OnMyContentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            SomeContainer source = (SomeContainer)d;
            FrameworkElement newValue = (FrameworkElement)e.NewValue;
            FrameworkElement oldValue = (FrameworkElement)e.OldValue;

            // validate newValue
            if (!IsValidMyContent(source, oldValue, newValue)) {
                // revert back to e.OldValue
                source._nestLevelMyContent++;
                source.SetValue(e.Property, e.OldValue);
                source._nestLevelMyContent--;

                // throw ArgumentException
                throw new ArgumentException("Invalid MyContentProperty value", "e");
            }

            if (source._nestLevelMyContent == 0) {
                // remember initial state
                source._initialMyContent = oldValue;
                source._requestedMyContent = newValue;
            }

            source._nestLevelMyContent++;

            // coerce newValue
            FrameworkElement coercedValue = (FrameworkElement)CoerceMyContent(d, e.NewValue);
            if (newValue != coercedValue) {
                // always set MyContentProperty to coerced value
                source.MyContent = coercedValue;
            }

            source._nestLevelMyContent--;

            if (source._nestLevelMyContent == 0 && source.MyContent != source._initialMyContent) {
                // fire changed event only at root level and when there is indeed a change
                source.OnMyContentChanged(oldValue, source.MyContent);
            }
        }
        /// <summary>
        /// MyContentProperty validation handler.
        /// </summary>
        /// <param name="value">New value of MyContentProperty.</param>
        /// <returns>
        /// Returns true if value is valid for MyContentProperty, false otherwise.
        /// </returns>
        private static bool IsValidMyContent(SomeContainer source, FrameworkElement oldValue, FrameworkElement newValue) {
            //place here your code for validating new value (if you need)

            //return false if newValue equals oldValue
            if (newValue.Equals(oldValue)) { return false; }

            return true;
        }
        /// <summary>
        /// MyContentProperty coercion handler.
        /// </summary>
        /// <param name="d">SomeContainer that changed its MyContent.</param>
        /// <param name="value">Event arguments.</param>
        /// <returns>
        /// Coerced effective value of MyContentProperty from input parameter value.
        /// </returns>
        private static object CoerceMyContent(DependencyObject d, object value) {
            SomeContainer source = (SomeContainer)d;
            FrameworkElement newValue = (FrameworkElement)value;

            //place here your code (if you need)

            return newValue;
        }
        /// <summary>
        /// MyContentProperty changed event.
        /// </summary>
        public event RoutedPropertyChangedEventHandler<FrameworkElement> MyContentChanged;

        /// <summary>
        /// Called by OnMyContentPropertyChanged static method to fire MyContentChanged event.
        /// </summary>
        /// <param name="oldValue">The old value of MyContent.</param>
        /// <param name="newValue">The new value of MyContent.</param>
        protected virtual void OnMyContentChanged(FrameworkElement oldValue, FrameworkElement newValue) {
            //place here your code (if you need)

            RoutedPropertyChangedEventArgs<FrameworkElement> e =
                new RoutedPropertyChangedEventArgs<FrameworkElement>(oldValue, newValue);
            if (MyContentChanged != null) {
                MyContentChanged(this, e);
            }
        }

        /// <summary>
        /// Cached previous value of MyContentProperty.
        /// </summary>
        private FrameworkElement _initialMyContent = null;
        /// <summary>
        /// Cached originally requested value of MyContentProperty by user.
        /// </summary>
        private FrameworkElement _requestedMyContent;
        /// <summary>
        /// level of recursive calls of PropertyChangedCallback, for implementing validation & coercion, 
        /// and preventing internal transitions from visible to client by not firing bogus changed notifications
        /// </summary>
        private int _nestLevelMyContent;
        #endregion public FrameworkElement MyContent

    }
}


Код

<UserControl x:Class="TestApp.MainPage"
             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"
             xmlns:local="clr-namespace:TestApp"
             mc:Ignorable="d"
             d:DesignHeight="300"
             d:DesignWidth="400">

    <Grid x:Name="LayoutRoot"
          Background="White">
        <StackPanel Width="300">
            <Button Content="click it!"
                    Click="Button_Click"
                    Height="30" />
            <local:SomeContainer>
                <local:SomeContainer.MyContent>
                    <TextBlock x:Name="MyLabel"
                               Text="Any text" />
                </local:SomeContainer.MyContent>
            </local:SomeContainer>
        </StackPanel>
    </Grid>
</UserControl>


Код

using System.Windows;
using System.Windows.Controls;

namespace TestApp {
    public partial class MainPage : UserControl {
        public MainPage() {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e) {
            this.MyLabel.Text = "hellow from code";
        }
    }
}


Это сообщение отредактировал(а) makaka - 1.8.2011, 23:02
PM MAIL   Вверх
Kefir
Дата 2.8.2011, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


«Hakuna Matata»
***


Профиль
Группа: Комодератор
Сообщений: 1878
Регистрация: 25.1.2003
Где: Tampere, Suomi

Репутация: 22
Всего: 87



Ну значит где-то в коде ты ставишь контент в null. И текст бокс растворяется. Поставь брейкпойнт на инменении dp с условием newvalue == null. И смотри откуда оно ставит null. 

Кстати, csproj в архиве битый (по крайней мере моя VSE 2010 открыть не шмогла).
PM MAIL WWW Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | WPF и Silverlight | Следующая тема »


 




[ Время генерации скрипта: 0.0659 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.