Как запустить метод UWP FrameworkElement SizeChanged для Visiblity.Collapsed?

Я хочу показать FrameworkElement, когда его ширина> 50, иначе свернуть его

private void PB_LocalDrive_SizeChanged(object sender, SizeChangedEventArgs e)
{
    var progressBar = sender as FrameworkElement;
    progressBar.Visibility = progressBar.ActualWidth > 50 ? Visibility.Visible : Visibility.Collapsed;
}

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

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

private void Parent_SizeChanged(object sender, SizeChangedEventArgs e)
{
    var stackPanel = sender as FrameworkElement;
    var progressBar = (ProgressBar)stackPanel.FindName("PB_LocalDrive");
    progressBar.Visibility = progressBar.ActualWidth > 50 ? Visibility.Visible : Visibility.Collapsed;
}

person alperen    schedule 24.09.2018    source источник


Ответы (2)


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

Никогда не изменяйте видимость или другие состояния макета элемента на основе его родительского текущего размера.

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

Во-первых, не используйте FindName, если у вас есть имя в вашем элементе управления, просто напрямую ссылайтесь на него, нет необходимости в дополнительных накладных расходах функции.

Во-вторых, используйте AdaptiveTrigger, это первый подход xaml, который чище и приятнее, чем подход кода, для получения дополнительной информации проверьте это: https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.AdaptiveTrigger

Наконец, если вы действительно хотите придерживаться подхода кода, то обязательно сравните с чем-то более солидным и определенным с точки зрения размеров, и это текущее окно вашего приложения, оно никогда не будет переполняться за пределами видимого пространства приложения, и это никогда не изменится, что бы ни происходило внутри его содержимого, он находится в прекрасном месте по адресу Window.Current.Bounds

person Xeorge Xeorge    schedule 24.09.2018
comment
AdaptiveTrigger — это именно то, что мне было нужно. Спасибо - person alperen; 25.09.2018
comment
Моя цель использования FindName — просто доступ к элементу внутри DataTemplate. Например, DataTemplate›Grid›TextBlock x:Name=TXT_Name. Если я хочу скрыть TXT_Name в Grid_PointerEntered, TXT_Name не доступен напрямую по имени. Является ли FindName правильным подходом для этого состояния или нет? - person alperen; 25.09.2018
comment
Я хорошо понял, собирался порекомендовать визуальные состояния, но, думаю, я ответил на вопрос напрямую. - person Mac; 25.09.2018

Учитывая, что x:Name вашего progressBar равно PB_LocalDrive, вы можете просто сделать следующее, и вам не нужно находить элемент через родителя, это будет работать, даже когда элемент свернут.

private void Parent_SizeChanged(object sender, SizeChangedEventArgs e)
{
    PB_LocalDrive.Visibility = PB_LocalDrive.ActualWidth > 50 ? Visibility.Visible : Visibility.Collapsed;
}
person Muhammad Touseef    schedule 24.09.2018