Подтвердить что ты не робот

Консолидация пользовательских элементов управления WPF, триггеры и события

Пользовательские элементы управления WPF

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

  • UIElement
  • FrameworkElement
  • Управление
  • ContentControl
  • HeaderedContentControl
  • ItemsControl
  • Селектор
  • RangeBase

Как написано в следующем учебнике: http://wpftutorial.net/HowToCreateACustomControl.html

Итак, я последовал за учебником и создал новый проект типа Custom Control Library, получил мой общий .xaml и мой код. Пока все хорошо.

Есть 3 типа или категории событий, которые я могу различать.

  • События, которые расходуются в окне (или контейнере), которые будут использовать мой элемент управления: это события, которые я хотел бы открыть снаружи. Как их написать?

  • События, связанные с самим элементом управления и не находящиеся снаружи; например, если мышь находится над моим контролем, и я хотел бы реагировать к тому, что. Я могу сделать это в XAML:

    <ControlTemplate.Triggers>
      <Trigger Property="IsMouseOver" Value="true">  
        <Setter Property="Fill" TargetName="LeftTraingularIndicator">  
          <Setter.Value>  
            <SolidColorBrush Color="Yellow" />  
          </Setter.Value>  
        </Setter>
      </Trigger>
    </ControlTemplate.Triggers>  
    

Предполагая, что у меня есть элемент с свойством fill в моем ControlTemplate, который называется x: name= "LeftTraingularIndicator"

Вопросы:

Теперь я хочу реагировать в своем XAML на IsMouseDown. Как мне это сделать? Триггера IsMouseDown отсутствует. Кроме того, что, если я хочу реагировать на это в коде? И еще дальше, что, если я хочу изменить LeftTraingularIndicator "Заполнить" из кода позади?

  1. События, связанные с подэлементами, которые являются частью визуального построение моего ControlTemplate, например, что, если я хочу реагировать в "IsMouseOver" из "LeftTraigularIndicator" в XAML/или даже в коде за кодом? Возможно даже оба.

Я пытаюсь в течение 2 дней... чувствую, что мне не хватает чего-то в моем понимании того, как все работает. Не нашел ни одного учебника, который бы глубоко объяснил эти вопросы.

Я хотел бы увидеть несколько строк примера для каждого из вопросов, которые я нашел здесь.

Спасибо.

4b9b3361

Ответ 1

После обширных исследований...

1) Выявление событий снаружи... Просто, как если бы вы выставлялись из любого другого класса.

public delegate void myDelegate(int someValue);  
public event myDelegate myEvent;

и где-то в вашем коде:

if(myEvent!=null)
  myEvent(5);

Ничего нового в этой части.

2) Из кода, созданного конструктором экземпляра

public MyCustomControl()
{
    MouseMove += MyCustomControl_MouseMove;
}


void MyCustomControl_MouseMove(object sender, MouseEventArgs e)
{
   //now you can react to the movement of the mouse.
   //if for example I want to address an element, let say a rectangle:

   var ele = (Rectangle)Template.FindName("myRect",this);
   ele.Fill=myNewBrush;

   // provided that we have an element named "myRect" (x:name="myRect") in
   // the generic.xaml style->Control Template-> which corresponds to that name.

}

3) Не рекомендуется - поскольку он относится к области пользовательских элементов управления, а не к пользовательским элементам управления. Пользовательские элементы управления - это "атомы", пользовательские элементы управления более подходят для объединение элементов управления.

Но не невозможно...

var myButton = (Button)Template.FindName("myButton",this);
myButton.OnMouseMove += ....

Просто имейте в виду, что:

  • Все, что должно быть известно в коде, должно быть названо.

  • Ваш xaml не должен знать, что делает код. (кроме! - продолжайте читать)

  • Части, которые должны быть известны в коде, должны иметь правильное имя, если вы создаете свой XAML.

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

Ответ 2

Если я правильно понял ваш вопрос - ниже мое объяснение.

Система событий WPF предлагает 3 типа событий: 1. Bubbling 2. Туннелирование 3. Прямой

Если событие определено (интенсивно) в качестве события барботирования, тогда событие пузырится от источника до его контейнера. Например: Если в сетке размещены две кнопки - Rectangle1 и Rectangle2, то любой щелчок по этим прямоугольникам разворачивается до Grid. Туннелирование - это противоположное, где события туннелируют от родителя к ребенку.

Есть прямые события, которые являются очень особенными - они применимы только в тех случаях, когда события не имеют смысла пузыряться. Например, в приведенном выше сценарии не имеет смысла пузырить событие MouseOver на любом из Rectangles - поскольку каждый раз, когда мышь входит в прямоугольник, событие разворачивается до Grid - это то, что кто-то может ожидать.

Ваш вопрос:

События, которые расходуются в окне (или контейнере), который будет использовать мой элемент управления: это те события, которые я хотел бы открыть снаружи. Как их записать?

Вам в основном нужно написать пузырящее событие. Ниже приведен пример из msdn, чтобы написать событие bubbling tap на кнопке (я сам не пробовал) Пример маршрутизируемого события:

public static readonly RoutedEvent TapEvent = EventManager.RegisterRoutedEvent(
"Tap", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyButtonSimple));

Ваш вопрос:

Вопросы: Теперь я хочу реагировать в своем XAML на IsMouseDown... как это сделать? нет "IsMouseDown" Trigger.. еще больше, что, если я хочу реагировать на это в коде? и еще дальше, что, если я хочу изменить LeftTraingularIndicator "Заполнить" из кода позади?

Кстати, у вас, похоже, есть путаница с событиями и триггерами (потому что я вижу, что вы используете их взаимозаменяемо). Хотя они связаны друг с другом, они не совпадают.

Возвращаясь к вашему вопросу - WPF позволяет запускать триггеры изменений свойств - в этом, по сути, вы подключаетесь к - IsMouseOver в этом случае. Но отсутствует то, что свойство является объектом ControlTemplate (который я не знаю, что это такое). Я просто экстраполирую, что целью ControlTemplate является прямоугольник. В этом случае у него нет свойства "IsMouseDown", чтобы вы могли подключить триггер свойств. И именно по этой причине вы не можете его найти. Другой вариант, который вы должны написать AttachedEvent (они очень похожи на AttachedProperties).. целая другая тема: (

Надеюсь, я старался изо всех сил:)