Получение значения свойства в родительском элементе управления из дочернего элемента управления - PullRequest
4 голосов
/ 21 января 2009

У меня есть ChildUserControl, который загружается внутри ParentUserControl. Страница хоста загружает ParentUserControl.

Мне нужно было бы получить доступ к свойствам в ParentUserControl из ChildUserControl.

Спасибо за ваше время

Ответы [ 7 ]

10 голосов
/ 21 января 2009

Платформа / язык и т. Д. Не ясны, поэтому этот ответ обязательно является расплывчатым ... однако в общем случае дочерний элемент управления не может получить доступ к свойствам родительского элемента (напрямую), поскольку множество различных типов родительских элементов управления может быть хозяином дочернего контроля. Дочерний объект не должен быть жестко запрограммирован для одного родителя, в противном случае это может быть также часть родителя.

Как правило, вы можете попытаться просто удалить требование - это звучит как странный дизайн. Однако некоторые фреймворки поддерживают что-то , например this - например, свойства зависимостей в WPF.

Дизайн на основе интерфейса (для родителя (ей)) - это один из подходов, но он не очень чистый. В .NET события и т. Д. Являются еще одним распространенным способом общения ребенка с родителем - ребенок представляет события, которые разные родители могут потреблять по-разному.

Кроме того, вы находитесь на территории тестирования / приведения родительского элемента (либо к классу, либо к интерфейсу) для доступа к деталям из родительского элемента - например:

ParentControlType parent = this.Parent as ParentControlType;
if(parent != null) {
    // access properties etc of "parent"
}

(здесь также можно использовать интерфейс; в любом случае, он немного хакерский ...)

Лично, вместо того, чтобы использовать этот тип приведения от ребенка, я бы предпочел, чтобы родитель взял контроль; родительский объект устанавливает свойства для дочернего элемента и слушает события (а не дочерний набор свойств для родительского элемента):

// in the parent
child.SomeProperty = 132;
child.SomePropertyChangd += delegate {
    // do something at the parent
};

Таким образом, ребенок не знает или не заботится о родителе. Все, что он знает, - это то, что он обладает свойствами (и т. Д.) И может уведомлять других людей об интересных изменениях.

1 голос
/ 21 января 2009

Можно получить доступ к родителю из дочернего элемента управления через ((ParentType) Me.Parent). Это не рекомендуется. Нет никакого способа узнать, что элемент управления не будет использоваться на другой странице / элементе управления. Компилятор не поймает это, это приведение вызовет исключение во время выполнения.

Лучший способ справиться с этим - предоставить родителю любую информацию, которая нужна дочернему элементу управления (создать открытые свойства или методы для элементов управления). Это может даже означать, что родительский элемент управления предоставляет строго типизированную ссылку на дочерний элемент управления (возможно, через интерфейс). Таким образом, компилятор гарантирует, что у вас не будет случая, когда дочерний элемент управления принимает родителя неправильного типа.

0 голосов
/ 02 февраля 2010

Если у вас есть 2 вложенных пользовательских элемента управления (UC):

UC1.ascx
| & Mdash; UC2.ascx

В UC1.ascx вы определяете публичную функцию или свойство, которые делают то, что вам нужно:
fnUC1 (пары)

В UC2.ascx вы можете достичь этой функции с помощью этого кода:

CType (parent.parent, UC1) .fnUC1 (пары) 1011 *
*

Если ваш элемент управления UC2 находится внутри другого контейнера (например, повторителя), вам также придется выйти из этого контейнера, и, таким образом, код будет:

CType (Parent.Parent.Parent, UC1) .fnUC1 (пары)

Я признаю, что это не "современное состояние" ... но оно работает для вложенных элементов управления, которые всегда работают вместе, например отображение данных родительского (UC1) / дочернего (UC2).

Надеюсь, это будет полезно.

Пьер.

0 голосов
/ 21 января 2009

Спасибо за ответы.

Я рассмотрю Reflection. Однако я слышал, что у него есть узкое место в производительности.

Джим - вы говорите:

~~

Лучший способ справиться с этим - предоставить родителю любую информацию, которая нужна дочернему элементу управления (создать открытые свойства или методы для элементов управления). Это может даже означать, что родительский элемент управления предоставляет строго типизированную ссылку на дочерний элемент управления (возможно, через интерфейс). Таким образом, компилятор гарантирует, что у вас не будет случая, когда дочерний элемент управления принимает родителя неверного типа.

~~

В моей ситуации и родитель, и дочерний элемент (ren) реализуют один и тот же интерфейс. Это плохой дизайн? Если я добавлю свойство родительской ссылки в интерфейс, будет ли это работать, учитывая, что родительский объект также реализует тот же интерфейс?

0 голосов
/ 21 января 2009

Вы можете использовать свойство this.Parent дочернего элемента управления, но если вы ищете более подходящее ОО-решение, вы бы этого не сделали. Разрешение ребенку узнать что-либо о родителе в конечном итоге связывает их каким-то образом и ограничивает повторное использование. В большинстве случаев это представляет интерес только для теории, и если вы создаете какой-то быстрый одноразовый сайт, вы можете нарушать его по мере необходимости. Но более правильным способом является использование событийных коммуникаций.

0 голосов
/ 21 января 2009

Вы можете использовать Reflection следующим образом:

public static T GetData<T>(this Control c, string propertyName, T defaultValue){
  Type t = obj.GetType();
  var prop = t.GetProperties().FirstOrDefault(p => p.Name == propertyName);
  if(prop == null) return defaultValue;
  else {
    object val = prop.GetValue(obj, null);
    if(val == null) return defaultValue;
    else return (T)val;
  }
}

Этот простой метод расширения, который расширяет «Control», но вы можете легко поместить это на что угодно (я использовал его на object, когда я передавал анонимные классы, что само по себе плохая идея!)

Тогда использование будет:

string someData = this.Parent.GetData("someProperty", string.Empty);
0 голосов
/ 21 января 2009

Извините, что не ясно. Платформа .NET и язык C #.

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

Согласно дизайну интерфейса, вы предлагаете, чтобы и родитель, и дочерний элемент (ren) реализовали общий интерфейс?

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