new не скрывает унаследованное свойство

Возможное дублирование:
Использование ключевого слова C # virtual + переопределение и новое

Я пытаюсь скрыть свое свойство UserControl Content следующим образом:

public partial class Tile : UserControl
{
    public new object Content
    {
        get { ... }
        set { ... }
    }
}

Но когда я устанавливаю Content своего UserControl, он ничего не делает (если я устанавливаю точку останова, она никогда не достигается):

<my:Tile Content="The content"/>

or

<my:Tile>The content</my:Tile>

Почему? Как я могу решить эту проблему?


person Nick    schedule 20.10.2012    source источник
comment
Что значит ничего не меняет?   -  person Kirk Woll    schedule 21.10.2012
comment
@KirkWoll Если я установил точку останова, она никогда не будет достигнута ...   -  person Nick    schedule 21.10.2012
comment
@ErikPhilips Свойство контента не виртуальное ... Вы знаете wpf?   -  person Nick    schedule 21.10.2012
comment
Если вы прочитаете ответ в ссылке, то поймете, почему это происходит. Короче говоря, свойство new не удаляет, не скрывает и не избавляется от одноименного свойства базовых типов. В вашем случае, когда какой-либо метод использует ваш Tile класс в качестве типа UserControl, он получит доступ к свойству UserControl.Content. Это базовое понимание того, как работает C #, и не имеет ничего общего с фреймворком, использующим C #.   -  person Erik Philips    schedule 21.10.2012
comment
@Erik WPF не использует свой класс в качестве типа UserControl, поэтому вы ошибаетесь. Он использует DependencyObject.GetValue / SetValue, поэтому проблема в том, что он не скрывает свойство зависимости.   -  person Mike Marynowski    schedule 21.10.2012
comment
Новое ключевое слово в этом контексте выполняет только одно действие. Это не дает компилятору сказать, что вы делаете что-то неправильно. С большой вероятностью, это не помешало вам сделать что-то неправильно. Вторая подсказка заключается в том, что вы не использовали или не могли использовать ключевое слово override. Значит, вы ничего не отменяли. Оригинальный метод все еще существует, не отменен.   -  person Hans Passant    schedule 21.10.2012
comment
@MikeMarynowski, угадайте, что, UserControl является производным из DependencecyObject. Поэтому то, что я сказал для любого базового объекта до Tile, верно. Если WPF использует объект Dependency, его новое содержимое объекта все равно будет игнорироваться. Это фундаментальное правило, определяющее, как компилятор C # работает с любым производным объектом.   -  person Erik Philips    schedule 21.10.2012
comment
Его новое содержимое объекта НЕ будет игнорироваться, потому что WPF этого не делает: ((UserControl) yourTileObject) .Content = blah; Скорее, он делает это: ((DependencyObject) yourTileObject) .SetValue (Tile.ContentProperty, мля); После динамического поиска ContentProperty, начиная с верха иерархии классов, а не снизу.   -  person Mike Marynowski    schedule 22.10.2012
comment
Вы можете очень быстро попробовать это сами. Я только что создал UserControl, добавил новое свойство содержимого, как описано ниже, бросил его в окно и установил его свойство Content для тестирования в XAML. Вы можете видеть, что UserControl.Content остается в своем значении по умолчанию, а Tile.Content устанавливается на test.   -  person Mike Marynowski    schedule 22.10.2012
comment
Это не дубликат, поскольку wpf вводит DependencyProperty, а ответ на самом деле не о ключевом слове new.   -  person Sinatr    schedule 10.11.2016


Ответы (2)


Проблема в том, что вы не скрываете фактическое свойство DependencyProperty, а только средство доступа get / set, которое WPF может или не всегда может использовать для установки значения DP. В WPF есть оптимизации, которые вместо этого напрямую вызывают DependencyObject.GetValue / SetValue.

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

public static readonly new DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(Tile));

public new object Content
{
    get { return this.GetValue(ContentProperty); }
    set { this.SetValue(ContentProperty, value); }
}

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

person Mike Marynowski    schedule 20.10.2012
comment
Не беспокойся о том, что мне делать, спасибо. можешь показать мне какой-нибудь код? - person Nick; 21.10.2012
comment
Как показывает ответ ниже, есть более эффективные способы использования существующего свойства содержимого. Но если вы действительно хотите скрыть базовое свойство, я обновлю ответ. - person Mike Marynowski; 21.10.2012
comment
Учитывая, что вы просите меня показать вам некоторый код, который регистрирует свойство зависимости, что на самом деле является самой основой WPF, я предполагаю, что вы довольно новичок в WPF, и я думаю, вам следует пересмотреть скрытие своего намерения, потому что мы, вероятно, можем предложить лучший способ сделать это. - person Mike Marynowski; 21.10.2012

Если вы хотите добавить свои собственные функции к свойству Content, вы, вероятно, ищете _ 2_. Таким образом, вы можете добавить свой собственный обработчик изменения свойства в производный класс. Это выглядело бы примерно так:

static Tile()
{
    ContentProperty.OverrideMetadata(typeof(Tile), new PropertyMetadata(null, OnContentChanged));
}

private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    // Your logic goes here.
}

ИЗМЕНИТЬ

Просто взглянул, и WPF уже позаботился об этом за вас. Вы можете просто переопределить OnContentChanged:

protected override void OnContentChanged(object oldContent, object newContent)
{
    base.OnContentChanged(oldContent, newContent);

    // Your logic goes here.
}
person Adi Lester    schedule 20.10.2012