Щелчок, перетаскивание и прокрутка холста

#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;
    }