簡體   English   中英

帶有MVVM應用程序中的Scrollviewer的畫布

[英]Canvas with Scrollviewer in MVVM application

為了使畫布自動調整其大小以使ScrollViewer正常工作,我創建了一個從Canvas派生的類,該類隨后重寫MeasureOverride方法以使畫布根據畫布上存在的UIElement調整其大小。

public class DesignerCanvas : Canvas
{
    protected override Size MeasureOverride(Size constraint)
    {
        Size size = new Size();
        foreach (UIElement element in Children)
        {
            double left = Canvas.GetLeft(element);
            double 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) && !double.IsNaN(desiredSize.Height))
            {
                size.Width = Math.Max(size.Width, left + desiredSize.Width);
                size.Height = Math.Max(size.Height, top + desiredSize.Height);
            }
        }

        // add some extra margin
        size.Width += 10;
        size.Height += 10;
        base.InvalidateMeasure();
        return size;
    }
}

XAML:

<ScrollViewer HorizontalScrollBarVisibility="Visible">
        <local:DesignerCanvas x:Name="designerCanvas"  AllowDrop="True">
            <ItemsControl Name="Shapes">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <Canvas />
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
            </ItemsControl>
        </local:DesignerCanvas>
    </ScrollViewer>

每當我將圖形直接添加到DesignerCanvas或從中刪除圖形時,scrollviewer都能正常工作! 除了我不是。 我正在使用MVVM方法,因此將畫布數據綁定到ObservableCollection

    private ObservableCollection<Shape> shapes = new ObservableCollection<Shape>();
    public ObservableCollection<Shape> Shapes 
    {
        get { return shapes; }
        set { shapes = value; }
    }

每當將項目添加到observablecollection中時,形狀就會顯示在畫布上。 但是,畫布本身無法正確調整大小,這導致我的scrollviewer無法正常工作。 這是預料之中的,因為我沒有直接操作DesignerCanvas,所以從未調用MeasureOverride。

我可以在DesignerCanvas上調用InvalidateMeasure,但這需要我的視圖模型具有有關視圖的知識。 如何在不破壞MVVM的情況下解決此問題?

編輯:我也想聽聽任何建議,如果實際上值得為這種問題保留這種模式。 最近,我覺得MVVM給我的問題多於解決方案。

Edit2:哦..好的,這個問題比我想象的要復雜得多。 根據Florian Gl的建議,我繼續在自己的視圖模型中創建了一個事件,然后在我的視圖中處理了該事件,以調用designerCanvas.InvalidateMeasure()。

這將在DesignerCanvas中調用我的MeasureOverride方法。 除非它無法正確調整我的畫布大小,所以scrollviewer仍然無法正常工作。 我注意到,我沒有將形狀直接添加到DesignerCanvas的子級中,而是添加到了與Canvas數據綁定的observablecollection中。 因此,在我的foreach語句中沒有UIElement可以循環通過

    protected override Size MeasureOverride(Size constraint)
    {
        Size size = new Size();

        ItemsControl itemsControl = Children.OfType<ItemsControl>().First();


        foreach (UIElement element in Children) //No UIElements inside Children
        {
            double left = Canvas.GetLeft(element);
            ...

現在我真的被卡住了。 我該如何規避這個問題?

我的活動想法:

  1. 在ViewModel中創建自己的事件:

     public delegate void MyCollectionChangedEventArgs(); public event MyCollectionChangedEventArgs MyCollectionChanged; 
  2. 在ViewModel中調用事件:

     if (MyCollectionChanged != null) { MyCollectionChanged(); } 
  3. 讓您的視圖了解該事件:

      MainWindowViewModel vm = new MainWindowViewModel(); vm.MyCollectionChanged += new MainWindowViewModel.MyCollectionChangedEventArgs(MainWindowViewModel_MyCollectionChanged); 

    要么

      MainWindowViewModel vm = (MainWindowViewModel)DataContext; vm.MyCollectionChanged += new MainWindowViewModel.MyCollectionChangedEventArgs(MainWindowViewModel_MyCollectionChanged); 
  4. 通話方式:

     void MainWindowViewModel_MyCollectionChanged() { designerCanvas.InvalidateMeasure() } 

編輯:我不知道我的以下建議是否在MeasureOverride-Method中工作,但是您可以嘗試:

    (MainWindowViewModel) mvm = (MainWindowViewModel)DataContext; 

    foreach (UIElement element in mvm.Shapes)
    { ... }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM