Статьи

Создание ползункового переключателя для Windows Phone 7 — изменение внешнего состояния

В моей последней статье я показал, как создать собственный элемент управления ползунком (также известный как ToggleSwitch ), но в нем отсутствовала одна важная функция — изменение внешних свойств. Ну, на самом деле вы можете изменить свойство IsOn из внешнего вызова, но это не повлияет на сам элемент управления — ползунок не будет двигаться.

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

ПРИМЕЧАНИЕ. Все упомянутые здесь операции выполняются внутри основного класса MyControl , который определяет поведение элемента управления.

Прежде всего, мне нужно добавить DependencyProperty :

public static readonly DependencyProperty IsOnProperty = DependencyProperty.Register("IsOn",typeof(bool), typeof(MyControl),
new PropertyMetadata(new PropertyChangedCallback(PropertyWasChanged)));

Обратите внимание, что я передаю пустоту — обратный вызов PropertyWasChanged . Он будет срабатывать при каждом изменении свойства (независимо от направления). Прежде чем перейти к обратному вызову, мне нужно изменить базовое свойство IsOn, чтобы связать его с зависимостью:

public bool IsOn
{
get
{
return (bool)GetValue(IsOnProperty);
}
set
{
SetValue(IsOnProperty, value);
}
}

Итак, давайте посмотрим на обратный вызов:

private static void PropertyWasChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PerformStateCheck((MyControl)d);
}

d — это DependencyObject, переданный в обратный вызов, и в этом случае это будет текущий экземпляр MyControl , у которого изменилось свойство. И вот еще один метод, который я нигде не упоминал — PerformStateCheck . Это метод, который запускает анимацию раскадровки (как я уже говорил, код из предыдущей статьи полностью пересматривается, когда речь идет о связывании свойств).

Вот как это выглядит:

static void PerformStateCheck(MyControl c)
{
if (grid == null)
{
grid = (Grid)VisualTreeHelper.GetChild(c, 0);
resourceDict = grid.Resources;
}

if (c.IsOn)
{
sBoard = resourceDict["mainAnimator"] as Storyboard;
sBoard.Begin();
}
else
{
sBoard = resourceDict["reverseAnimator"] as Storyboard;
sBoard.Begin();
}
}

Из последней статьи этот фрагмент кода был помещен непосредственно в обработчик событий Click . Больше нет, поскольку MyControl_Click больше не будет запускать анимацию , а, скорее, при изменении свойства IsOn (т. Е. При срабатывании обратного вызова). Состояние проверяется по переданному экземпляру MyControl — во фрагменте обратного вызова вы можете видеть, что я передаю вызывающий экземпляр при проверке. Я должен упомянуть, что grid , resourceDict и sBoard являются статическими — необходимая модификация, учитывая природу вызовов, которые я использую (все начинается с PropertyChangedCallback DependencyProperty ).

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

void MyControl_Click(object sender, RoutedEventArgs e)
{
((MyControl)sender).IsOn = !((MyControl)sender).IsOn;
}

Теперь это работает! Вы можете инициировать изменение свойства со страницы хоста, и состояние элемента управления изменится соответственно.