gpt4 book ai didi

WPF MVVM 管理多个窗口

转载 作者:行者123 更新时间:2023-12-03 10:46:11 24 4
gpt4 key购买 nike

希望在 WPF/C# MVVM 中编写一个便笺应用程序,不是因为我们需要另一个,而是因为它可以帮助我复习一些我正在尝试变得更加熟悉的事情。
我的问题是关于如何处理多个窗口的一些指导。例如,将有多个注释未绑定(bind)到主窗口。我想跟踪所有打开的窗口,例如,如果一个收到焦点,我可能想把其他笔记窗口放在前面,但不要从我选择的窗口中移除焦点,而不是寻找任何人给我代码,只是一些关于如何处理它的指导。

最佳答案

也许这可以在某种程度上帮助你:http://kentb.blogspot.nl/2011/11/application-im-currently-working-on-top.html

文章的重要部分:

What I did instead was had the WindowItemsControl create WindowItemsControlItem instances as containers. These containers are really just surrogates for the Window they represent. When they're initialized, they display the Window. When they're destroyed, they close the Window. In addition, if a Window is closed ahead of time, the corresponding data item is removed from the underlying collection and thus too the surrogate from the visual tree.


public class WindowItemsControl : ItemsControl
{
    public static readonly DependencyProperty ShowDialogProperty = DependencyProperty.Register(
        "ShowDialog",
        typeof(bool),
        typeof(WindowItemsControl));
 
    public static readonly DependencyProperty OwnerProperty = DependencyProperty.Register(
        "Owner",
        typeof(Window),
        typeof(WindowItemsControl),
        new FrameworkPropertyMetadata(OnOwnerChanged));
 
    public static readonly DependencyProperty WindowStartupLocationProperty = DependencyProperty.Register(
        "WindowStartupLocation",
        typeof(WindowStartupLocation),
        typeof(WindowItemsControl));
 
    public static readonly DependencyProperty RemoveDataItemWhenWindowClosedProperty = DependencyProperty.Register(
        "RemoveDataItemWhenWindowClosed",
        typeof(bool),
        typeof(WindowItemsControl),
        new FrameworkPropertyMetadata(true));
 
    static WindowItemsControl()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(WindowItemsControl), new FrameworkPropertyMetadata(typeof(WindowItemsControl)));
    }
 
    public bool ShowDialog
    {
        get { return (bool)this.GetValue(ShowDialogProperty); }
        set { this.SetValue(ShowDialogProperty, value); }
    }
 
    public Window Owner
    {
        get { return this.GetValue(OwnerProperty) as Window; }
        set { this.SetValue(OwnerProperty, value); }
    }
 
    public WindowStartupLocation WindowStartupLocation
    {
        get { return (WindowStartupLocation)this.GetValue(WindowStartupLocationProperty); }
        set { this.SetValue(WindowStartupLocationProperty, value); }
    }
 
    public bool RemoveDataItemWhenWindowClosed
    {
        get { return (bool)this.GetValue(RemoveDataItemWhenWindowClosedProperty); }
        set { this.SetValue(RemoveDataItemWhenWindowClosedProperty, value); }
    }
 
    protected override DependencyObject GetContainerForItemOverride()
    {
        return new WindowItemsControlItem(this);
    }
 
    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return item is WindowItemsControlItem;
    }
 
    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        (element as WindowItemsControlItem).Window.Content = item;
    }
 
    protected override bool ShouldApplyItemContainerStyle(DependencyObject container, object item)
    {
        // the item container style will be applied to the windows, not to the containers (which are surrogates for the window)
        return false;
    }
 
    private static void OnOwnerChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
    {
        var windowItemsControl = (WindowItemsControl)dependencyObject;
        var owner = (Window)e.NewValue;
 
        for (var i = 0; i < windowItemsControl.Items.Count; ++i)
        {
            var container = windowItemsControl.ItemContainerGenerator.ContainerFromIndex(i) as WindowItemsControlItem;
 
            if (container == null)
            {
                continue;
            }
 
            container.Window.Owner = owner;
        }
    }
}

  • 它声明了一些属性(ShowDialog、Owner、WindowStartupLocation)来帮助它显示子窗口

  • 它声明了一个 RemoveDataItemWhenWindowClosed 属性,该属性可用于防止控件在窗口关闭时删除数据项。这在关闭或其他以编程方式而不是由用户关闭窗口的情况下很有用

  • 我不将 ItemContainerStyle 应用到容器本身,而是保留以便我可以将它们应用到它们所代表的 Windows

  • 我还确保将所有者的任何更改应用于任何现有的 Windows

  • 默认样式被覆盖以删除不必要的东西,如边框,因为 WindowItemsControl 永远不会在屏幕上真正可见

  • public class WindowItemsControlItem : FrameworkElement
    {
        private readonly WindowItemsControl windowItemsControl;
        private readonly Window window;
     
        static WindowItemsControlItem()
        {
            // there is no need for these items to be visible as they are simply surrogates for the windows that they display
            VisibilityProperty.OverrideMetadata(typeof(WindowItemsControlItem), new FrameworkPropertyMetadata(Visibility.Collapsed));
        }
     
        public WindowItemsControlItem(WindowItemsControl windowItemsControl)
        {
            windowItemsControl.AssertNotNull("windowItemsControl");
     
            this.windowItemsControl = windowItemsControl;
            this.window = this.CreateWindow(windowItemsControl);
     
            this.Loaded += delegate
            {
                if (this.windowItemsControl.ShowDialog)
                {
                    this.window.ShowDialog();
                }
                else
                {
                    this.window.Show();
                }
            };
     
            this.Unloaded += delegate
            {
                this.window.Close();
            };
        }
     
        public Window Window
        {
            get { return this.window; }
        }
     
        private Window CreateWindow(WindowItemsControl windowItemsControl)
        {
            var window = new Window
            {
                Owner = windowItemsControl.Owner,
                WindowStartupLocation = windowItemsControl.WindowStartupLocation
            };
     
            BindingOperations.SetBinding(window, Window.DataContextProperty, new Binding("Content") { Source = window });
            BindingOperations.SetBinding(window, Window.StyleProperty, new Binding("ItemContainerStyle") { Source = windowItemsControl });
            BindingOperations.SetBinding(window, Window.ContentTemplateProperty, new Binding("ItemTemplate") { Source = windowItemsControl });
            BindingOperations.SetBinding(window, Window.ContentTemplateSelectorProperty, new Binding("ItemTemplateSelector") { Source = windowItemsControl });
     
            window.Closed += delegate
            {
                // orphan the content because it might be hosted somewhere else later (including in another window)
                window.Content = null;
     
                // if the window closes, attempt to remove the original item from the underlying collection, which will result in this surrogate being removed too
                if (windowItemsControl.RemoveDataItemWhenWindowClosed)
                {
                    var editableItems = windowItemsControl.Items as IEditableCollectionView;
     
                    if (editableItems != null && editableItems.CanRemove)
                    {
                        editableItems.Remove(this.DataContext);
                    }
                }
            };
     
            return window;
        }
    }

  • WindowItemsControl 上的相关属性绑定(bind)到 Windows 本身的正确属性

  • 初始化代理时显示窗口,卸载代理时关闭

  • 如前所述,在代理项被销毁之前关闭的 Windows(可能通过用户单击关闭按钮)会导致基础集合中的相关数据项被删除(除非 RemoveDataItemWhenWindowClosed 属性已设置为 false)。反过来,这将导致代理从可视化树中移除。换句话说,如果我关闭一个小部件窗口,相应的 WidgetViewModel 将从我的小部件 View 模型集合中删除。然后,ItemsControl 将从可视树中删除相关的代理容器。
  • 关于WPF MVVM 管理多个窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25221951/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com