每次在AvalonDock中选择选项卡时,都会为ViewModel重新创建视图

时间:2019-02-25 08:59:57

标签: c# wpf avalondock

使用AvalonDock,我遇到了一个对我来说似乎有些奇怪的问题。

情况

我有一个ViewModel的ObservableCollection绑定到DockingManager的DocumentSource属性。我将项目添加到此集合中,因此将文档添加到DockingManager中:选择正确的ViewModel视图(UserControl),因为我为每个ViewModel指定了一个DataTemplate。

问题

以上所有作品。但是,当我在AvalonDock中的两个选项卡之间切换时,每次选择一个选项卡时都会重新创建视图(调用InitializeComponent())。这会导致问题,原因是无法持久保存选择,并且静态UIElements在添加到已在使用中的位置时会导致异常。

即使在这个问题上花了很多时间,我也不确定自己在做什么错。使用模板选择器代替当前选择正确视图的方法无效。

欢迎任何想法!

编辑1

有趣的是,我在这里使用的AvalonDock版本具有更好的效果。那是2016年某个时候的2.0.0版本,而不是当前版本3.5.0。完全相同的代码可以像我期望的那样使用旧版本,而不适用于最新版本。

实施

下面是我的AvalonDock实现的一个缩写版本。

主视图:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="container">
  <div class="row">
    <div class="container mt-5">
      <h2 class="header-text">Practical business advice and knowhow<br>customized to your needs</h2>
    </div>
  </div>
<div class="d-flex footer justify-content-sm-center align-content-between flex-sm-wrap flex-lg-nowrap">
  <div class="d-flex justify-content-left">
    <div class="watch">
      <div class="watch-elements">
        <img src="assets/img/icons/icon2.svg">
        <p>Watch Presenation</p>
      </div>
    </div>
  </div>

  <div class="d-flex justify-content-center">
    <div class="mouse">
      <div class="mouse-elements">
        <img src="assets/img/icons/Icon1.svg"><br>
        <p>Scroll Down</p>
      </div>
    </div>
  </div>

  <div class="d-flex justify-content-right align-items-center">
    <div class="chat-bot">
      <img src="assets/img/06w.png">
      <p>Hi, can I help you?</p>
      <img src="assets/img/icons/icon3.svg" style="float: right; margin-right: -60px; margin-top: -39px;">
    </div>
  </div>
</div>
</div>

主要ViewModel:

<Window ... >
    <Window.Resources>
        <DataTemplate DataType="{x:Type local:Workspace1}">
            <local:Workspace1View />
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <StackPanel Orientation="Horizontal">
            <Button Content="1" Command="{Binding Path=OpenWorkspace1Command}" Margin="2" />
        </StackPanel>
        <ad:DockingManager 
            Grid.Row="1" 
            DocumentsSource="{Binding Path=Workspaces}" 
            AllowMixedOrientation="True">
        </ad:DockingManager>
    </Grid>
</Window>

工作区视图(请注意,在ListView中向下滚动时,在离开选项卡并返回时,滚动位置会重置,导致重新创建View):

public class MainWindowViewModel : ViewModelBase
{
    private RelayCommand _openWorkspace1Command;

    public ObservableCollection<WorkspaceBase> Workspaces { get; } = new ObservableCollection<WorkspaceBase>();

    public ICommand OpenWorkspace1Command => _openWorkspace1Command ?? (_openWorkspace1Command = new RelayCommand(() => 
    {
        Workspaces.Add(new Workspace1());
    }));
}

工作区ViewModel:

<UserControl ...>
    <Grid>
        <ListView ItemsSource="{Binding Items}" />
    </Grid>
</UserControl>

最后是抽象的WorkspaceBase类:

public class Workspace1 : WorkspaceBase
{
    public override void OnWorkspaceOpened() { }

    public List<string> Items { get; }

    public Workspace1()
    {
        Items = new List<string>();

        for (int i = 0; i < 10000; i++) Items.Add("Item " + i.ToString());
    }
}

1 个答案:

答案 0 :(得分:1)

似乎这是AvalonDock本身的问题。此版本的控件可解决以下问题:https://github.com/Dirkster99/AvalonDock