如果页面未显示在框架中,则WPF Visualbrush不会更新

时间:2019-06-28 07:14:57

标签: c# wpf canvas visualbrush

朋友! 有一个主窗口,它包含一个框架,我可以在其中切换页面。 我有一个带有画布的页面。后台流中的画布在镶嵌视图中以图像形式接收数据。

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,但这没有产生结果。

1 个答案:

答案 0 :(得分:1)

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

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

每次执行此操作时,您的应用都会从给定的来源中加载新的Page。如果当前页面恰好是上面有您的Page的{​​{1}},则导航将创建一个新的Canvas实例。如果不是,并且Canvas中没有为Page设置JournalEntry.KeepAlive="true",则Canvas的内容只会从每个Frame文件中重新创建时间显示出来,并随之创建一个新的Source。在某些时候,某些东西会断开连接或被过早破坏。即使将Canvas设置为KeepAlive,您也可能最终会在内存中加载True的多个实例。您想绑定到哪一个...?

有些另类的方法使我无法自拔:

  1. Canvas本身缓存在您的视图模型中,并将Image上的CanvasPage都绑定到此。

  2. 在视图模型中缓存整个VisualBrush,然后根据需要切换其内容。

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

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 } 的{​​{1}}事件中的图像之间切换:

Click