0

朋友们!有一个主窗口,它包含一个框架,我用它在页面之间切换。我有一个有画布的页面。后台流中的画布以马赛克视图中的图像形式接收数据。

foreach (var item in CoreData.fillWallArray.GetConsumingEnumerable())
{
    if (File.Exists(item.PathFile))
    {
          Application.Current.Dispatcher.Invoke(new Action(() =>
          {
               Image image = new Image();
               image.Source = BitmapImageFromFile(item.PathFile);
               image.Width = (int)Math.Truncate((CoreData.settings.CellWidth * 30) / 2.54);
               image.Height = (int)Math.Truncate((CoreData.settings.CellHeight * 30) / 2.54);
               Canvas.SetLeft(image, item.Column * (int)Math.Truncate((CoreData.settings.CellWidth * 30) / 2.54));
               Canvas.SetTop(image, item.Row * (int)Math.Truncate((CoreData.settings.CellHeight * 30) / 2.54));
               can.Children.Add(image);
          }));
          Thread.Sleep(100);
    }
}

我的任务是将这个画布带到第二个屏幕。为此,我创建了第二个窗口,并作为上下文传递了我需要的画布。

var _BroadcastWindow = new BroadcastWindow();
_BroadcastWindow.DataContext = this.can;
_BroadcastWindow.Show();

在第二个窗口中,我链接了数据。

<Grid>
    <Grid.Background>
        <VisualBrush Visual="{Binding}"/>
    </Grid.Background>
</Grid>

一切正常,画布中的数据同步显示在第二个窗口中。但是一旦我切换到另一个页面,Visualbrush 就不再更新了。一旦我切换回带有我在第二个窗口中看到的画布的页面,它就会更新。可能是什么问题呢?在后台线程中向画布添加数据时,我也尝试调用 Measure、Arrange、UpdateLayout,但这并没有产生结果。

4

1 回答 1

1

我假设当您说“转到另一页”时,您的意思是:

frame.Navigate(new System.Uri("Page2.xaml", UriKind.RelativeOrAbsolute));

每次执行此操作时,您的应用都会Page从给定来源加载一个新的。如果当前页面恰好是Page您所在的页面Canvas,则导航将创建一个新Canvas实例。如果没有,并且您的 没有为设置JournalEntry.KeepAlive="true",那么每次显示时都会从文件中重新创建 的内容,并使用它创建一个新的内容。某些东西会在某个时候断开连接或过早破坏。即使使用set to ,您也可能最终会在内存中加载多个实例。你想绑定哪一个...?PageCanvasFrameSourceCanvasKeepAliveTrueCanvas

我想到了一些替代方法:

  1. 将自身缓存Image在您的视图模型中,并将您的Canvason thePage和 the绑定到那VisualBrush

  2. 将整体缓存Canvas在您的视图模型中,然后根据需要切换其内容。

第二种方法只需要对您的代码进行最少的更改,因此我可以提供一个工作示例(尽管我不知道它是否是最佳的):

Page1.xaml(显示画布的页面):

<Grid>
    <ContentControl Content="{Binding canvas, Source={x:Static local:CanvasViewModel.Instance}}" />
</Grid>

BroadcastWindow.xaml

<Grid>
    <Grid.Background>
        <VisualBrush Visual="{Binding}"/>
    </Grid.Background>
</Grid>

用于保存画布的示例单例视图模型:

public class CanvasViewModel
{   
    Rectangle r = new Rectangle
    {
        Fill = Brushes.Orange,
        Width = 200,
        Height = 100
    };

    Ellipse e = new Ellipse
    {
        Fill = Brushes.DodgerBlue,
        Width = 100,
        Height = 100
    };


    public Canvas canvas { get; set; }

    public void Initialize()
    {
        canvas = new Canvas();
        Switch(1);
    }

    // Here the contents of the canvas are switched
    // I called it from Click events of two Buttons outside of Frame
    // In your case, I imagine it will be something like this:
    // public void LoadImage(string path) {...}
    public void Switch(int imageNr)
    {
        switch (imageNr)
        {
            case 1:
                    canvas.Children.Clear();
                    canvas.Children.Add(r);
                break;
            case 2:
                {
                    canvas.Children.Clear();
                    canvas.Children.Add(e);
                }
                break;
            default:
                break;
        }
    }

    #region CONSTRUCTOR

    static CanvasViewModel() { }
    private CanvasViewModel() { }

    private static CanvasViewModel GetAppViewModelHolder()
    {
        CanvasViewModel vh = new CanvasViewModel();
        vh.Initialize();
        return vh;
    }

    #endregion

    #region SINGLETON Instance

    private static readonly object _syncRoot = new object();
    private static volatile CanvasViewModel instance;

    public static CanvasViewModel Instance
    {
        get
        {
            var result = instance;
            if (result == null)
            {
                lock (_syncRoot)
                {
                    if (instance == null)
                    {
                        result = instance = GetAppViewModelHolder();
                    }
                }
            }
            return result;
        }
    }

    #endregion
}

在Frame 之外的情况Click下在图像之间切换:Button

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        CanvasViewModel.Instance.Switch(2);
    }
于 2019-06-28T10:52:35.533 回答