Могу ли я задержать привязку элемента ui, если элемент в настоящее время не виден. Иногда у меня есть форма, в которой есть скрытые/минимизированные элементы, я бы не хотел их обновлять, если они не отображаются на экране. Я подозреваю, что ответ отрицательный, но никогда не больно спрашивать?WPF: остановить привязку, если элемент пользовательского интерфейса не отображается
ответ
Нет встроенного способа сделать это, но вы можете написать его самостоятельно.
Хитрость заключается в том, чтобы обернуть связывание в собственной внутренней линии разметки, который использует оригинальный переплет, но добавляет новое поведение вокруг него (например, путем установки UpdateSourceTrigger в Явный, когда вы не хотите связывание работать.
Вот пример (который задерживает передачу связывающей свои данных):
http://www.paulstovell.com/wpf-delaybinding
Теперь, есть много возможных условия краев с отключением привязок для невидимых элементов управления, особенно вокруг, показывая и скрывая элементы управления, так что я бы не стал напишите общее расширение для этого, но можете быть в вашем конкретном приложении, это может быть полезно.
thats wierd, я написал аналогичную вещь - http://www.codeproject.com/KB/WPF/DelayedBindingTextBox.aspx –
Ответ отрицательный, потому что привязка может быть причиной повторного создания элемента. Поэтому, если привязка не работает с скрытыми элементами управления, это не позволит привязке сделать ее видимой снова.
Для обходного пути у меня есть привязка к видимости объекта, когда объект установлен на видимый, свойство запускает конструкцию элемента позади него, который имеет привязку через ContentPresenter
.
Я знаю, что это старый вопрос, но поскольку я не смог найти реализованный класс или что-то еще, я сделал это сам, следуя @Nir ответу.
Это расширение разметки, который оборачивает нормальное связывание только действительно связывается, когда свойство объекта IsVisible
становится истинным в первый раз:
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace MakupExtensions {
[MarkupExtensionReturnType(typeof(object))]
public class LazyBindingExtension : MarkupExtension {
public LazyBindingExtension() {
}
public LazyBindingExtension(PropertyPath path) : this() {
Path = path;
}
public IValueConverter Converter {
get;
set;
}
[TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))]
public CultureInfo ConverterCulture {
get;
set;
}
public object ConverterParamter {
get;
set;
}
public string ElementName {
get;
set;
}
[ConstructorArgument("path")]
public PropertyPath Path {
get;
set;
}
public RelativeSource RelativeSource {
get;
set;
}
public object Source {
get;
set;
}
public UpdateSourceTrigger UpdateSourceTrigger {
get;
set;
}
public bool ValidatesOnDataErrors {
get;
set;
}
public bool ValidatesOnExceptions {
get;
set;
}
public bool ValidatesOnNotifyDataErrors {
get;
set;
}
private Binding binding;
private DependencyObject bindingTarget;
private DependencyProperty bindingTargetProperty;
public override object ProvideValue(IServiceProvider serviceProvider) {
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (valueProvider != null) {
bindingTarget = valueProvider.TargetObject as DependencyObject;
bindingTargetProperty = valueProvider.TargetProperty as DependencyProperty;
if (bindingTargetProperty == null || bindingTarget == null) {
throw new NotSupportedException($"The property '{valueProvider.TargetProperty}' on target '{valueProvider.TargetObject}' is not valid for a LazyBinding. The LazyBinding target must be a DependencyObject, and the target property must be a DependencyProperty.");
}
binding = new Binding {
Path = Path,
Converter = Converter,
ConverterCulture = ConverterCulture,
ConverterParameter = ConverterParamter
};
if (ElementName != null) {
binding.ElementName = ElementName;
}
if (RelativeSource != null) {
binding.RelativeSource = RelativeSource;
}
if (Source != null) {
binding.Source = Source;
}
binding.UpdateSourceTrigger = UpdateSourceTrigger;
binding.ValidatesOnDataErrors = ValidatesOnDataErrors;
binding.ValidatesOnExceptions = ValidatesOnExceptions;
binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors;
return SetBinding();
}
return null;
}
public object SetBinding() {
var uiElement = bindingTarget as UIElement;
if (uiElement != null && !uiElement.IsVisible) {
uiElement.IsVisibleChanged += UiElement_IsVisibleChanged;
}
else {
ConsolidateBinding();
}
return bindingTarget.GetValue(bindingTargetProperty);
}
private void ConsolidateBinding() => BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding);
private void UiElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) {
var uiElement = sender as UIElement;
if (uiElement != null && uiElement.IsVisible) {
uiElement.IsVisibleChanged -= UiElement_IsVisibleChanged;
ConsolidateBinding();
}
}
}
}
Применение:
<ItemsControl ItemsSource="{mx:LazyBinding Documents}"/>
В этом примере, он будет привязываться только тогда, когда ItemControl IsVisible
станет истинным в первый раз.
Он не отцепляется, когда IsVisible
снова получает ложную информацию, но я думаю, что кто-то может поменять его по мере необходимости.
Улучшенная MarkupExtension, которая обертывает нормальную привязку к автоматической привязке/развязыванию модели данных, если видимая изменена.
См. Предыдущую версию here.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;
namespace UtilsWPF
{
[MarkupExtensionReturnType(typeof(object))]
public class LazyBindingExtension : MarkupExtension
{
public LazyBindingExtension()
{ }
public LazyBindingExtension(PropertyPath path) : this()
{
Path = path;
}
#region Properties
public IValueConverter Converter { get; set; }
[TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))]
public CultureInfo ConverterCulture { get; set; }
public object ConverterParamter { get; set; }
public string ElementName { get; set; }
[ConstructorArgument("path")]
public PropertyPath Path { get; set; }
public RelativeSource RelativeSource { get; set; }
public object Source { get; set; }
public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
public bool ValidatesOnDataErrors { get; set; }
public bool ValidatesOnExceptions { get; set; }
public bool ValidatesOnNotifyDataErrors { get; set; }
private Binding binding;
private UIElement bindingTarget;
private DependencyProperty bindingTargetProperty;
#endregion
#region Init
public override object ProvideValue(IServiceProvider serviceProvider)
{
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (valueProvider != null)
{
bindingTarget = valueProvider.TargetObject as UIElement;
if (bindingTarget == null)
{
throw new NotSupportedException($"Target '{valueProvider.TargetObject}' is not valid for a LazyBinding. The LazyBinding target must be a UIElement.");
}
bindingTargetProperty = valueProvider.TargetProperty as DependencyProperty;
if (bindingTargetProperty == null)
{
throw new NotSupportedException($"The property '{valueProvider.TargetProperty}' is not valid for a LazyBinding. The LazyBinding target property must be a DependencyProperty.");
}
binding = new Binding
{
Path = Path,
Converter = Converter,
ConverterCulture = ConverterCulture,
ConverterParameter = ConverterParamter
};
if (ElementName != null)
{
binding.ElementName = ElementName;
}
if (RelativeSource != null)
{
binding.RelativeSource = RelativeSource;
}
if (Source != null)
{
binding.Source = Source;
}
binding.UpdateSourceTrigger = UpdateSourceTrigger;
binding.ValidatesOnDataErrors = ValidatesOnDataErrors;
binding.ValidatesOnExceptions = ValidatesOnExceptions;
binding.ValidatesOnNotifyDataErrors = ValidatesOnNotifyDataErrors;
return SetBinding();
}
return null;
}
public object SetBinding()
{
bindingTarget.IsVisibleChanged += UiElement_IsVisibleChanged;
updateBinding();
return bindingTarget.GetValue(bindingTargetProperty);
}
#endregion
#region Event Handlers
private void UiElement_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
updateBinding();
}
#endregion
#region Update Binding
private void updateBinding()
{
if (bindingTarget.IsVisible)
{
ConsolidateBinding();
}
else
{
ClearBinding();
}
}
private bool _isBind;
private void ConsolidateBinding()
{
if (_isBind)
{
return;
}
_isBind = true;
BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding);
}
private void ClearBinding()
{
if (!_isBind)
{
return;
}
BindingOperations.ClearBinding(bindingTarget, bindingTargetProperty);
_isBind = false;
}
#endregion
}
}
Применение:
<ItemsControl ItemsSource="{utils:LazyBinding Documents}"/>
- 1. WPF: преобразовать строку в элемент пользовательского интерфейса
- 2. WPF C# Пользовательский элемент пользовательского интерфейса?
- 3. Изменение пользовательского интерфейса WPF
- 4. Преобразование пользовательского интерфейса из Windows Forms в привязку данных WPF
- 5. Создание пользовательского интерфейса в WPF
- 6. WPF - Приостановка темы пользовательского интерфейса?
- 7. WPF MVVM - Обновление пользовательского интерфейса
- 8. Свойство пользовательского контроля WPF, не получающее привязку данных
- 9. Дизайн пользовательского интерфейса в WPF - создание нестандартного пользовательского интерфейса
- 10. Как ссылаться на элемент пользовательского интерфейса из ViewModel (WPF)?
- 11. WPF ждет завершения пользовательского интерфейса
- 12. Как подождать элемент пользовательского интерфейса без сбоя.
- 13. Что такое элемент пользовательского интерфейса?
- 14. Получить элемент пользовательского интерфейса (внутри расширителя) по имени в WPF
- 15. Изменение триггера события WPF Другой элемент пользовательского интерфейса
- 16. Получить элемент пользовательского интерфейса в координатах касания
- 17. Копировать элемент пользовательского интерфейса с adorner
- 18. Самый легкий элемент пользовательского интерфейса
- 19. Как остановить устаревшие обновления пользовательского интерфейса?
- 20. iOS получить элемент пользовательского интерфейса из XCUIElement
- 21. UWP: Обновление пользовательского интерфейса через привязку данных из фонового потока
- 22. остановить поток пользовательского интерфейса до HTTP-ответов
- 23. Android, Элемент моего пользовательского ListView не отображается
- 24. Как остановить обновление пользовательского интерфейса (через службу)?
- 25. WPF UI Freezes - конфликт пользовательского интерфейса?
- 26. Ошибка при соединении нескольких компонентов пользовательского интерфейса в WPF
- 27. WPF ждут ключи от потока пользовательского интерфейса
- 28. Обработка второго потока пользовательского интерфейса в WPF
- 29. WPF Listbox пользовательский элемент изображения не отображается
- 30. Могу ли я использовать элемент управления WPF WebBrowser в качестве интерфейса пользовательского интерфейса в C#?
почему вы хотите сделать это? для производительности? –
да исполнение, его на самом деле лень (лень - мать изобретения), потому что я должен удалять вещи из дерева, если они не видны, чтобы получить нужную мне производительность. –