0

Я использую привязку на основе соглашения от Caliburn.Micro, но у меня есть небольшая проблема:Как связать свойство управления?

Как установить свойство, с которым привязывается привязка? Если я создаю элемент управления с x:Name="SomeProperty", как выбрать, если значение SomeProperty должно быть привязано к Value Объект моего контроля, OnClick Событие моего контроля или что-то другое, например Content или Tag?

Пример: У меня есть HyperlinkButton, что я хочу привязать к определенному URL-адресу, и я хочу привязать OnClick к обработчику событий в моей модели ViewModel.

<HyperlinkButton x:Name="BookDetailsViewModel_InfoLink" Content="Read more" /> 

Свойство Content однако не заполнен Read more, но с значением URL. В этом примере, как я:

  • Установите навигационный URI на значения URL в моей ViewModel собственности
  • Установите содержание в «Подробнее»
  • Укажите обработчик событий в моей ViewModel, что будет обрабатывать щелчок

Может ли кто-нибудь мне помочь?

+0

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

+0

Я просто хочу, чтобы это сработало, мне все равно, работает ли оно с соглашениями или без них. Некоторый явный код привязки отлично работает со мной, но когда я использую {Binding SomeProperty}, он не работает. –

+0

Добавлено объяснение того, как сделать это как на основе конвенций, так и явно. Дайте мне знать, если это поможет. – Charleh

ответ

1

Вы можете настроить конгресс-менеджер для каждого типа элемента в CM. По умолчанию вне коробки implemententation применяется к любому элементу, который не имеет явную настройку

Чтобы добавить новую конвенцию вы просто звоните ConventionManager.AddElementConvention

метод выглядит следующим образом (от источника CM)

/// <summary> 
/// Adds an element convention. 
/// </summary> 
/// <typeparam name="T">The type of element.</typeparam> 
/// <param name="bindableProperty">The default property for binding conventions.</param> 
/// <param name="parameterProperty">The default property for action parameters.</param> 
/// <param name="eventName">The default event to trigger actions.</param> 
public static ElementConvention AddElementConvention<T>(DependencyProperty bindableProperty, string parameterProperty, string eventName) 
{ 
    return AddElementConvention(new ElementConvention 
    { 
     ElementType = typeof(T), 
     GetBindableProperty = element => bindableProperty, 
     ParameterProperty = parameterProperty, 
     CreateTrigger =() => new EventTrigger { EventName = eventName } 
    }); 
} 

Как вы можете видеть, это занимает несколько арга - вам нужно передать свойство по умолчанию для привязок, действий и триггера, например,

ConventionManager.AddElementConvention<HyperlinkButton>(HyperlinkButton.NavigateUri, "NavigateUri", "Click"); 

(предполагая, что событие клики называются Нажмите)

Поскольку вы не связывание Content свойства любой больше (потому что соглашение является в настоящее время связывает NavigateUri), вы можете просто оставить это как есть и она должна оставаться "подробнее ...

Так что теперь у вас есть HyperlinkButton контроля, который должен связать по соглашению с NavigateUri и вызвать метод, который разделяет его имя, когда Click события.

Edit:

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

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

<HyperlinkButton Content="Read more..." NavigationURI="{Binding SomeUri}" cal:Message.Attach="[Event Click] = [Action HyperlinkClicked($this.NavigateUri)" /> 

, но это, вероятно, лучше пойти конвенционного маршрут :)

Edit:

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

<HyperlinkButton x:Name="SomeLink" Content="Read more..." cal:Message.Attach="HyperlinkClicked(SomeLink)" /> 

CM знает, что, поскольку вы установили NavigateUri в качестве параметра действия по умолчанию, он должен захватить это и передать его методу, указанному в привязке к действию. Мне интересно, будет ли работать и $this (вам, вероятно, понадобится $this.NavigateUri). Вы можете сделать это через элементы управления, например.

<TextBox x:Name="SomeTextBox" /> 
<HyperlinkButton x:Name="SomeLink" Content="Read more..." cal:Message.Attach="HyperlinkClicked(SomeTextBox)" /> 

выше будет проходить Text свойства текстового поля к методу HyperlinkClicked по умолчанию.

+0

Я пробовал явное решение, и он приходит к обработчику событий моей модели просмотра, но аргумент пуст. Мой метод выглядит так: 'public void HyperlinkClicked (EventArgs args)' Я передаю здесь неправильный тип аргумента? Я не мог понять, какой аргумент он должен принять (как узнать об этом?). –

+0

CM не использует 'EventArgs' - он использует тип свойства. Если вы перейдете в кодировку и объявите HyperlinkButton и посмотрите, какой тип является свойством «NavigateURI» (возможно, это строка или URI?), И используйте это как тип аргумента. Если вы сомневаетесь, установите тип метода как «объект» и точку останова - см. Тип аргумента, переданного как CM. CM передаст null параметрам, которые он не может соответствовать предоставленному, поэтому он не должен генерировать исключение, но он вызовет метод независимо. Моя догадка - это 'public void HyperlinkClicked (string uri)' будет работать. (нормально, я соврал, говорит, что его System.Uri) – Charleh

+0

Хмм, моя гиперссылка привязана к строке, но я получаю «нуль» даже время, даже когда я устанавливаю параметр как объект. Это мой XAML: ' ' –