2013-09-09 6 views
1

Я пытаюсь установить динамический источник для содержимого Attached Property, но это не работает. Попытка понять, почему, но я не могу понять это.Прикрепленное свойство и DynamicResource

В принципе, я уверен, реализации водяного знака на текстовом поле, используя код доступен по адресу: Watermark/hint text/placeholder TextBox in WPF предоставленного Джоном Myczek и использовать его в качестве так:

<TextBox Text="{Binding SomeProperty}"> 
    <helper:WatermarkService.Watermark> 
      <TextBlock FontStyle="Italic" Text="{DynamicResource SomeResource}" /> 
    </helper:WatermarkService.Watermark> 
</TextBox> 

внутренних TextBlock работает нормально, если это за пределами WatermarkService.Watermark прилагается имущество. SomeResource по какой-то причине пуст.

Мои ресурсы загружаются как this.Resources.MergedDictionaries.Add(lastDictionary);, так как приложение локализовано и данные извлекаются из центрального места.

Имеются ли элементы управления в прикрепленных свойствах равными ресурсами, установленными как их «родители»? Что здесь не так? Спасибо

+0

Из вашего описания это звучит скорее как проблема с кодом 'Watermark' ... вы можете это показать? – Sheridan

+0

Thx. Как сказано в сообщении, код доступен по адресу http://stackoverflow.com/questions/833943/watermark-hint-text-textbox-in-wpf в сообщении John Myczek – saamorim

ответ

1

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

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

Не так просто, как иметь общедоступный метод AddLogicalChild, потому что тогда вы испортили всю систему. Теперь вопрос заключается в том, кто несет ответственность за это. Общее решение может заключаться в создании пользовательского TextBox, который переопределяет логические дочерние методы и возвращает также текстовый блок водяного знака.

Это не глобальное решение, но в вашем случае, вы могли бы иметь собственное текстовое поле переопределение свойства LogicalChildren так:

public class WaterTextBox : TextBox 
{   
    protected override IEnumerator LogicalChildren 
    { 
     get 
     { 
      ArrayList list = new ArrayList(); 
      list.Add(WatermarkService.GetWatermark(this)); 
      return (IEnumerator)list.GetEnumerator(); 
     } 
    } 
} 

Помните, что это только временное решение, и таким образом будет работать только на пользовательском текстовых с динамическими ресурсами.

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

public class WaterTextBox : TextBox 
{   
    protected override IEnumerator LogicalChildren 
    { 
     get 
     { 
      ArrayList list = new ArrayList(); 
      IEnumerator enumerator = base.LogicalChildren; 
      while (enumerator.MoveNext()) 
      { 
       list.Add(enumerator.Current); 
      } 
      object watermark = WatermarkService.GetWatermark(this); 
      if (watermark != null && !list.Contains(watermark)) 
      { 
       list.Add(WatermarkService.GetWatermark(this)); 
      } 
      return (IEnumerator)list.GetEnumerator(); 
     } 
    } 
} 

Чтобы сделать его более общим, вы должны определить такой интерфейс, как IWatermark, определяющий свойство IsWaterMarkAdded, которое будет реализовано вашим пользовательским TextBox и ComboBox и будет использоваться службой водяных знаков. Контролирует значение этого свойства. Таким образом, вы можете расширить функциональность для вашего TextBox и ComboBox, но все же это не расширяемое решение для любого элемента управления.

+0

. Вы правы, так как Textblock.Parent is null, но как мне установить его правильно, так как в строке 3 конструктора уже есть 'this.contentPresenter.Content = водяной знак;' где водяной знак является «текстовым полем» – saamorim

+0

Тем не менее, текстовый блок может иметь другой логический родительский элемент.Логические и визуальные деревья разные. –

+0

Спасибо. Я проверю ваше решение и посмотрю, подходит ли это. Не хотел иметь настраиваемые элементы управления для этого, но я все равно проверю. Если вы запомните любой способ сделать это, я буду рад, если вы сообщите нам об этом. С уважением – saamorim