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

问题描述 投票:0回答:1

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

情况

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

问题

以上都是有效的。但是,当我在AvalonDock中的选项卡之间切换时,每次选择选项卡时都会重新创建视图(调用InitializeComponent())。这会导致问题导致选择不会持久化,并且静态UIElements会在已经使用时添加到某处时导致异常。

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

欢迎任何想法!

编辑1

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

履行

下面是我对AvalonDock实现的略微缩写版本。

主要观点:

<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>

主ViewModel:

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());
    }));
}

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

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

工作区ViewModel:

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());
    }
}

最后是抽象的WorkspaceBase类:

public abstract class WorkspaceBase : ViewModelBase, IDisposable
{
    RelayCommand _closeCommand;

    public virtual string DisplayName { get; }
    public virtual ImageSource Icon { get; }
    public virtual bool HideOnClose { get; } = false;
    public virtual bool IsCloseable { get; } = true;

    protected WorkspaceBase() { }

    public ICommand CloseCommand => _closeCommand ?? (_closeCommand = new RelayCommand(CloseCommand_executed, CloseCommand_canExecute));

    public delegate void WorkspaceRequestCloseEventHandler(object sender, WorkspaceRequestCloseEventArgs e);

    public event WorkspaceRequestCloseEventHandler RequestClose;

    void CloseCommand_executed()
    {
        Dispose();
        this.RequestClose?.Invoke(this, new WorkspaceRequestCloseEventArgs());
    }

    private bool CloseCommand_canExecute()
    {
        return IsCloseable;
    }

    public abstract void OnWorkspaceOpened();

    public void Dispose()
    {
        this.OnDispose();
    }

    protected virtual void OnDispose()
    {
    }
}
c# wpf avalondock
1个回答
1
投票

似乎这是AvalonDock本身的一个问题。此版本的控件修复了所描述的问题:https://github.com/Dirkster99/AvalonDock

© www.soinside.com 2019 - 2024. All rights reserved.