Скрыть элемент управления, когда другой элемент перекрывает его
У меня довольно большая проблема с элементами управления окнами, размещенными в WPF. Когда, например, пользователь прокручивает окно, размещенный элемент управления переходит в верхнюю часть окна, хотя он должен быть скрыт.
Я знаю, что это известная проблема и поведение по умолчанию размещенных элементов управления, но я думаю, что ее можно решить, если видимость элемента управления каким-либо образом связана с: перекрывают ли его другие элементы управления или нет. Если другие элементы управления перекрываются, он должен стать Свернутым или Скрытым, в противном случае он должен быть Видимым.
Я сделал какое-то решение для этого, но я сделал это для события ScrollChanged объекта ScrollViewer, и оно работает только в особых ситуациях. Если кто-то знает, как добиться этого с помощью связывания, чтобы его можно было применить к любому размещенному элементу управления, поделитесь своими идеями.
1 ответ
Для этой же проблемы мы реализовали нечто любопытное...
Хост форм Windows не зависит от Z-порядка, поэтому средство просмотра прокрутки не сможет частично скрыть / обрезать его для области, которая видна под средством просмотра прокрутки.
Итак, у нас было два варианта...
Используйте хост формы Windows для размещения в нем остальной части пользовательского интерфейса WPF, что означает, что мы отменяем владение пользовательским интерфейсом. WindowsFormsHost должен содержать весь пользовательский интерфейс, имеющий средство просмотра с прокруткой на основе WinForms, которое, в свою очередь, будет содержать пользовательский интерфейс WPF.
Реализуйте смещение прокрутки для вычисленной высоты хоста оконных форм, и когда пользовательские прокрутки добавляют это смещение к позиции наблюдателя прокрутки и скрывают хост форм ветра (
Visibility = Hidden
и НЕCollapsed
). Таким образом, это дает эффект, что вы не можете частично прокрутить хост winforms, но полностью прокрутить его из средства просмотра прокрутки. И потому что winformshost являетсяHidden
(не свернутый) он продолжает занимать такую большую высоту внутри невидимой области под средством просмотра прокрутки (таким образом сохраняя свое положение прокрутки).
Дайте мне знать, если это направит вас в правильном направлении.
Вы можете сделать небольшой трюк. Когда вы объявляетеWindowsFormsHost
, его родительский элемент является первым компонентом HWND. Обычно это корневое окно. Таким образом, область обрезки элементов управления - это все окно. Я покажу пример с WPFScrollViewer
.
<Window>
<Grid>
<ScrollViewer Margin="20,50">
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Window>
В этом случае поведение будет таким, как вы описали. Кнопки будут внеScrollViewer
границы. Но есть способ создать "промежуточный" элемент HWND для обрезкиWinForms
площадь над ScrollViewer
. Просто поместите еще одинWindowsFormsHost
с ElementHost
как показано ниже:
<Grid>
<WindowsFormsHost Margin="20,50">
<ElementHost x:Name="This is clip container">
<ScrollViewer>
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</ElementHost>
</WindowsFormsHost>
</Grid>
Теперь область клипа для кнопок ElementHost
а также WinForms
Button
s будет обрезаться им при прокрутке. Также вы можете создатьControlTemplate
за ContentContol
и повторно используйте его там, где вам это нужно.
<ControlTemplate x:Key="ClipConteiner" TargetType="{x:Type ContentControl}">
<WindowsFormsHost>
<ElementHost>
<ContentPresenter />
</ElementHost>
</WindowsFormsHost>
</ControlTemplate>
<Grid>
<ContentControl Template="{StaticResource ClipConteiner}" Margin="20,50">
<ScrollViewer>
<ItemsControl ItemsSource="{StaticResource StringArray}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<WindowsFormsHost>
<wf:Button />
</WindowsFormsHost>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</ContentControl>
</Grid>