#wpf #canvas #scrollviewer #itemspaneltemplate
#wpf #холст #scrollviewer #itemspaneltemplate
Вопрос:
У меня есть поле списка с ItemsPanelTemplate холста. Я знаю, что ScrollViewer не будет работать с холстом, если ему не заданы высота и ширина. Я не хочу присваивать холсту высоту и ширину, потому что они не всегда будут постоянными. Есть ли какие-либо другие обходные пути или приемы, которые кто-либо использовал для решения этой ситуации. Я знаю, что я не могу быть единственным с этой проблемой. Заранее спасибо, вот мой код на данный момент.
Другая проблема заключается в том, что я не могу разместить ScrollViewer внутри ItemsPanelTemplate, потому что внутри него может быть вложен только один элемент.
Это также ограничивает меня в размещении холста внутри сетки для получения позиционирования.
XAML:
<!--Core Viewer-->
<ScrollViewer x:Name="scrollViewer"
VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden">
<ListBox x:Name="objCoreViewer"
ItemsSource="{Binding ItemsSource}"
Background="LightGray"
SelectionChanged="objCoreViewer_SelectionChanged"
ItemTemplateSelector="{DynamicResource CoreViewerDataTemplateSelector}"
ItemContainerStyleSelector="{DynamicResource ItemContainerStyleSelector}"
PreviewMouseWheel="objCoreViewer_PreviewMouseWheel">
<!-- Core Map Canvas -->
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas x:Name="objCoreViewerCanvas"
Background="Transparent">
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding Path=Value, ElementName=ZoomSlider}"
ScaleY="{Binding Path=Value, ElementName=ZoomSlider}" />
</Canvas.LayoutTransform>
</Canvas>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</ScrollViewer>
Ответ №1:
Чтобы заставить холст расти на основе дочерних элементов внутри него, вам нужно переопределить событие MeasureOverride холста в пользовательском классе, который наследуется от Canavas. Этот код отлично работает для меня:
protected override System.Windows.Size MeasureOverride(System.Windows.Size constraint)
{
Size toReport = new Size();
foreach (UIElement element in this.InternalChildren)
{
//Get the left most and top most point. No using Bottom or Right in case the controls actual bottom and right most points are less then the desired height/width
var left = Canvas.GetLeft(element);
var top = Canvas.GetTop(element);
left = double.IsNaN(left) ? 0 : left;
top = double.IsNaN(top) ? 0 : top;
element.Measure(constraint);
Size desiredSize = element.DesiredSize;
if (!double.IsNaN(desiredSize.Width) amp;amp; !double.IsNaN(desiredSize.Height))
{
//left = desiredSize.Width;
//top = desiredSize.Height;
toReport.Width = toReport.Width > left desiredSize.Width ? toReport.Width : left desiredSize.Width;
toReport.Height = toReport.Height > top desiredSize.Height ? toReport.Height : top desiredSize.Height;
}
}
//Make sure scroll includes the margins incase of a border or something
toReport.Width = this.Margin.Right;
toReport.Height = this.Margin.Bottom;
return toReport;
}