簡體   English   中英

ScrollViewer中的Silverlight畫布大小調整

[英]Silverlight Canvas Sizing within a ScrollViewer

我正在使用C#創建Silverlight 4網站。 在其中一頁中,我要彼此相鄰放置兩個面板。 左側是地圖控件,右側是圖像。 這很容易,但是我還希望能夠單擊圖像並將PushPin像對象(例如地圖)一樣放置,因此我將圖像放在畫布中並僅繪制圓圈。 問題在於圖像可能會很大,我需要能夠滾動圖像。 我嘗試了幾種不同的方法來實現這一目標,但到目前為止還沒有運氣。

下一篇文章的答案似乎像是要走的路,但是必須對Silverlight進行更新才能使其失效: WPF:如何使畫布自動調整大小?

一個類似的解決方案建議從頭開始制作Canvas,但我遇到了同樣的問題。

我的大多數嘗試都是在屏幕上盡可能多地顯示圖像,但是沒有滾動條(仍顯示為灰色),或者在加載圖像時頁面僅變白。

以下是我當前選擇要加載的圖像的方式:

        OpenFileDialog dialog = new OpenFileDialog();
        dialog.Filter = "Image Files (*.png, *.jpg)|*.jpg;*.png";
        if(dialog.ShowDialog() == true) {
            BitmapImage bitmap = new BitmapImage();
            FileStream stream = dialog.File.OpenRead();
            bitmap.SetSource(stream);
            TheImage.Source = bitmap;
        }

可能有更好的解決方案,但這應該可以解決問題。

我創建了一個小的固定尺寸ScrollViewer,其中包含一個Canvas和一個圖像。 然后,我使用一種行為來修改畫布的大小以匹配圖像的大小。 該行為還處理ImageOpened事件,以在打開圖像后設置正確的圖像大小。

這是xaml:

<ScrollViewer Width="200" Height="200" HorizontalScrollBarVisibility="Auto">
    <Canvas x:Name="TheCanvas">
        <Image x:Name="TheImage">
            <i:Interaction.Behaviors>
                <Views:ResizeCanvasBehaviour Canvas="{Binding ElementName=TheCanvas}"/>
            </i:Interaction.Behaviors>
        </Image>
    </Canvas>
</ScrollViewer> 

確保將i聲明為xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"並且b與您放置行為的名稱空間匹配。

這是行為的代碼:

public class ResizeCanvasBehaviour : Behavior<Image>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;
        AssociatedObject.ImageOpened += AssociatedObject_ImageOpened;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged;
        AssociatedObject.ImageOpened -= AssociatedObject_ImageOpened;
    }

    private void AssociatedObject_ImageOpened(object sender, RoutedEventArgs e)
    {
        BitmapSource bitmapSource = AssociatedObject.Source as BitmapSource;
        if (bitmapSource == null)
        {
            return;
        }

        AssociatedObject.Width = bitmapSource.PixelWidth;
        AssociatedObject.Height = bitmapSource.PixelHeight;

        Resize();
    }

    private void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        Resize();
    }

    public Canvas Canvas
    {
        get { return GetValue(CanvasProperty) as Canvas; }
        set { SetValue(CanvasProperty, value); }
    }

    public static readonly DependencyProperty CanvasProperty = DependencyProperty.Register(
        "Canvas",
        typeof(Canvas),
        typeof(ResizeCanvasBehaviour),
        new PropertyMetadata(null, CanvasPropertyChanged));

    private static void CanvasPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((ResizeCanvasBehaviour)d).OnCanvasPropertyChanged();
    }

    private void OnCanvasPropertyChanged()
    {
        if (Canvas != null)
        {
            Resize();
        }
    }

    private void Resize()
    {
        if ((AssociatedObject != null) && (Canvas != null))
        {
            Canvas.Width = AssociatedObject.ActualWidth;
            Canvas.Height = AssociatedObject.ActualHeight;
        }
    }
}

要加載圖像,請執行以下操作。 我在后面的代碼中這樣做是為了提高速度,但是理想情況下,您應該將其放在視圖模型中,然后將數據綁定到xaml中的image Source屬性:

BitmapImage bi = new BitmapImage();
bi.UriSource = new Uri("http://farm7.static.flickr.com/6149/5942401995_a5a3fd3919_z.jpg");
TheImage.Source = bi;

原來,我要做的最起碼的工作是將畫布的Width和Height設置為BitmapImage實例的PixelWidth和PixelHeight。

這就是Paul在解決方案中所做的事情(以一種更為復雜的方式),但是由於某種原因,當在本地加載圖像時,不會調用resize事件處理程序。

我嘗試了幾種不同的建議解決方案,但從未獲得想要的結果。 這是唯一可行的解​​決方案。

暫無
暫無

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

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