#c# #wpf #dependency-properties
#c# #wpf #зависимость-свойства
Вопрос:
Я разрабатываю раскрывающийся элемент управления списком учетных записей, который будет использоваться в моем приложении. Выпадающий список вызовет службу и получит список доступных учетных записей, а также предоставит свойство «SelectedAccount» для выбранного элемента в выпадающем списке. SelectedAccount будет являться DependencyProperty, поскольку он должен быть связан потребителями элемента управления AccountDropdown, и он должен быть двусторонне привязан, чтобы отражать существующий SelectedAccount.
AccountDropdown.asmx прост, он содержит поле со списком:
<ComboBox SelectedItem="{Binding Path=SelectedAccount, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"...
Выбранный элемент поля со списком привязан к свойству, которое зарегистрировано как
DependencyProperty.Register("SelectedAccount", typeof(IAccount), typeof(AccountDropdown),
new UIPropertyMetadata(null));
… и обычное свойство:
#region SelectedAccount
/// <summary>
/// Selected account
/// </summary>
public IAccount SelectedAccount
{
get { return (IAccount)GetValue(SelectedAccountProperty); }
set { SetValue(SelectedAccountProperty, value); }
}
#endregion SelectedAccount
Свойства определены в файле с кодом … а контекст данных установлен на «this»… таким образом, привязка установлена правильно.
Когда я использую этот элемент управления, мне нужно привязать SelectedAccount к свойству ViewModel для другого представления, например:
<Controls:AccountDropdown SelectedAccount="{Binding Path=SelectedAccount, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
Когда я запускаю приведенный выше код и меняю выбор в выпадающем списке, я получаю систему.Исключение StackOverflow. Я даже не могу его отладить, исключение выдается из Windows.Base.dll .
Я уже целый день борюсь с этим … буду признателен за любую помощь.
** Примечание: ** Я написал несколько элементов управления WPF со свойствами зависимостей, и они работают нормально, но когда я их использую, я явно указываю значение в файле .asmx. В этом случае я снова привязываю, когда использую свойство. Я предполагаю, что для предоставления связываемого свойства может потребоваться некоторый дополнительный трюк.
Ответ №1:
Хорошо, как это часто бывает, решение было простым. DataContext элемента управления AccountDropdown неявно присваивался самому себе, отсюда и бесконечный цикл. Просто укажите DataContext для использования DataContext элемента управления, в котором он использовался (и, следовательно, с использованием предполагаемой привязки ViewModel):
<Controls:AccountDropdown DataContext="{Binding}" SelectedAccount="{Binding Path=SelectedAccount, Mode=TwoWay}" />
Мне все еще нужно выяснить, как указать элементу управления использовать контекст данных элемента управления, в котором он находится … если я это выясню, я опубликую это здесь … или, если кто-нибудь из вас знает, пожалуйста, пролейте немного света.
Еще раз спасибо тем, кто ответил.
Комментарии:
1. Дочерний элемент управления неявно «получает» datacontext от своего родительского элемента. Часть DataContext=»{Binding}» ничего не добавляет.
2. На самом деле это не так. Это было то, что решило проблему. И поскольку datacontext указывал на элемент управления, а не на родительский, вот почему бесконечный цикл. Я видел это и с другими элементами управления, хотя у меня не было бесконечного цикла. В расширенном наборе инструментов WPF есть несколько элементов управления, которые требуют явной настройки контекста данных, иначе они не будут работать.
3. Я ссылался на значение по умолчанию, а не на то, что глупые люди делают в своих элементах управления. 😉
Ответ №2:
Я предполагаю, что метод SelectedAccountChanged обновляет поле и тем самым вызывает бесконечную рекурсию, что приводит к переполнению стека.
Для проверки: удалите SelectedAccountChanged из свойства DependencyProperty.Зарегистрируйте вызов, чтобы убедиться, что это источник ошибки, а затем проверьте сам метод.
Если вам нужна помощь, опубликуйте метод там.
Комментарии:
1. Спасибо, Эрно… Я обновил вопрос некоторыми дополнительными деталями. На самом деле я добавил обратный вызов только для того, чтобы проверить, «изменяется» ли значение, и в режиме отладки он один раз нажимал на этот код, но метод ничего не делал. Я снова удалил его (и воспроизвел проблему на всякий случай), проблема была обновлена с помощью этой информации и некоторых дополнительных деталей. Еще раз спасибо.