.NET WPF सत्रों के बीच विंडो का आकार याद रखें


93

मूल रूप से जब उपयोगकर्ता मेरे आवेदन की विंडो का आकार बदलता है, तो मैं चाहता हूं कि आवेदन उसी आकार का हो जब आवेदन फिर से खोला जाए।

पहले तो मैंने SizeChanged इवेंट को संभालने और ऊँचाई और चौड़ाई को बचाने के लिए, लेकिन मुझे लगता है कि इसका आसान समाधान होना चाहिए।

बहुत सरल समस्या है, लेकिन मुझे इसका आसान हल नहीं मिल रहा है।


2
कृपया ध्यान दें कि यदि आप आकार और स्थिति दोनों को फिर से बना रहे हैं (जैसा कि नीचे दिए गए अधिकांश कोड नमूने हैं), तो आप उस किनारे वाले मामले को संभालना चाहेंगे, जहां किसी ने मॉनिटर को अनप्लग किया हो कि विंडो अंतिम बार प्रस्तुत की गई थी, ताकि आप उसे प्रस्तुत न कर सकें खिड़की बंद स्क्रीन।
ओमेर रविव

@OmerRaviv क्या आपको एक उदाहरण मिला है कि किनारे के मामले को ध्यान में रखा जाए?
एंड्रयू ट्रक

मेरे पास टिप्पणी जोड़ने के लिए बहुत कम प्रतिष्ठा है, इसलिए मैंने यह नया awnser बनाया। मैं RobJohnson की स्थापना सहित लांस क्लीवलैंड के रूप में एक ही समाधान का उपयोग करता हूं , लेकिन यह काम नहीं करता है यदि आप इसे उप विंडो के लिए उपयोग करते हैं और एक ही समय में उनमें से अधिक को खोलना चाहते हैं ...
AelanY

जवाबों:


121

User.config फ़ाइल में मान सहेजें।

आपको सेटिंग फ़ाइल में मान बनाने की आवश्यकता होगी - यह गुण फ़ोल्डर में होना चाहिए। पाँच मान बनाएँ:

  • Top प्रकार का double
  • Left प्रकार का double
  • Height प्रकार का double
  • Width प्रकार का double
  • Maximizedप्रकार का bool- धारण करने के लिए कि खिड़की अधिकतम है या नहीं। यदि आप अधिक जानकारी संग्रहीत करना चाहते हैं तो एक अलग प्रकार या संरचना की आवश्यकता होगी।

पहले दो से 0 और दूसरे दो के लिए अपने आवेदन के डिफ़ॉल्ट आकार और अंतिम एक के लिए प्रारंभिक।

एक Window_OnSourceInitialized ईवेंट हैंडलर बनाएँ और निम्न जोड़ें:

this.Top = Properties.Settings.Default.Top;
this.Left = Properties.Settings.Default.Left;
this.Height = Properties.Settings.Default.Height;
this.Width = Properties.Settings.Default.Width;
// Very quick and dirty - but it does the job
if (Properties.Settings.Default.Maximized)
{
    WindowState = WindowState.Maximized;
}

नोट: सेट विंडो प्लेसमेंट को विंडो के स्रोत इनिशियलाइज्ड इवेंट में जाना चाहिए, कंस्ट्रक्टर नहीं, अन्यथा यदि आपने विंडो को दूसरे मॉनिटर पर अधिकतम किया है, तो यह हमेशा प्राथमिक मॉनिटर पर अधिकतम पुन: प्रारंभ होगा और आप सक्षम नहीं होंगे इसे एक्सेस करने के लिए।

एक Window_Closing घटना हैंडलर बनाएँ और निम्नलिखित जोड़ें:

if (WindowState == WindowState.Maximized)
{
    // Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
    Properties.Settings.Default.Top = RestoreBounds.Top;
    Properties.Settings.Default.Left = RestoreBounds.Left;
    Properties.Settings.Default.Height = RestoreBounds.Height;
    Properties.Settings.Default.Width = RestoreBounds.Width;
    Properties.Settings.Default.Maximized = true;
}
else
{
    Properties.Settings.Default.Top = this.Top;
    Properties.Settings.Default.Left = this.Left;
    Properties.Settings.Default.Height = this.Height;
    Properties.Settings.Default.Width = this.Width;
    Properties.Settings.Default.Maximized = false;
}

Properties.Settings.Default.Save();

यह विफल हो जाएगा यदि उपयोगकर्ता डिस्प्ले क्षेत्र को छोटा करता है - या तो एक स्क्रीन को डिस्कनेक्ट करके या स्क्रीन रिज़ॉल्यूशन को बदलकर - जबकि आवेदन बंद है, इसलिए आपको एक चेक जोड़ना चाहिए कि मान लगाने से पहले वांछित स्थान और आकार अभी भी मान्य है।


5
दरअसल, प्रोग्राम फाइल में एप्कोफिग फाइल में स्कोप "यूजर" के साथ सेटिंग सेव नहीं की जाती है, लेकिन यूजर के एप्लिकेशन डेटा डायरेक्टरी में यूजर.कॉन्फिग फाइल में होती है। तो यह कोई समस्या नहीं है ...
थॉमस लेवेस्क

7
वास्तव में आप सेटिंग्स में "WindowState" जोड़ सकते हैं। प्रकार चुनें -> ब्राउज़ करें -> प्रस्तुतिफ़्रेमवर्क -> सिस्टम। Windows -> WindowState :)
मार्टिन Vseticka

2
एफडब्ल्यूआईडब्ल्यू, मैं आवेदन के क्रैश होने के मामले में आकार में परिवर्तन किए गए हैंडलर से भी ऐसा करता हूं। वे एक अपवादित अपवाद प्रसंस्करण के साथ दुर्लभ हैं, लेकिन जब वे रहस्यमय तरीके से करते हैं तो उपयोगकर्ता को खोए हुए आकार / स्थान के साथ दंडित क्यों किया जाता है।
थॉमस

7
इस कोड में एक बग है, यदि उपयोगकर्ता अपनी दूसरी स्क्रीन पर विंडो खोलता है, तो कंप्यूटर से उस स्क्रीन को डिस्कनेक्ट कर देता है, अगली बार जब वे विंडो खोलते हैं, तो इसे ऑफ स्क्रीन प्रस्तुत किया जाएगा। यदि विंडो मोडल है, तो उपयोगकर्ता ऐप के साथ बिल्कुल भी इंटरैक्ट नहीं कर पाएगा और समझ नहीं पाएगा कि क्या चल रहा है। स्क्रीन निर्देशांक DPI पर निर्भर मानों को परिवर्तित करने के
ओमेर रवीव

2
@OmerRaviv - यह बग नहीं है, लेकिन सीमा है :) गंभीरता से - मैंने समस्या के उस पहलू को संबोधित नहीं किया।
ChrisF

73

वास्तव में आपको ऐसा करने के लिए कोड-पीछे का उपयोग करने की आवश्यकता नहीं है (सेटिंग्स को बचाने के अलावा)। आप विंडो आकार और स्थिति को इस तरह से सेट करने के लिए एक कस्टम मार्कअप एक्सटेंशन का उपयोग कर सकते हैं:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:my="clr-namespace:WpfApplication1"
        Title="Window1"
        Height="{my:SettingBinding Height}"
        Width="{my:SettingBinding Width}"
        Left="{my:SettingBinding Left}"
        Top="{my:SettingBinding Top}">

आप इस मार्कअप एक्सटेंशन के लिए कोड यहां देख सकते हैं: http://www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/


4
मुझे यह उत्तर चुने हुए स्वीकृत उत्तर से अधिक पसंद है। बहुत बढ़िया।
मस्जिद

6
+1 - मुझे बाइंडिंग और एक्सटेंशन का उपयोग पसंद है! यदि आप WindowState को अपनी बाध्य सेटिंग में जोड़ते हैं, तो यह पूर्ण क्षमताएँ प्रदान करता है। वैकल्पिक रूप से, यदि आपके पास DataContext में उपयोगकर्ता सेटिंग्स उपलब्ध हैं, तो आप कुछ का उपयोग कर सकते हैं {Binding Settings.Height}, आदि
Matt DeKrey

इस दृष्टिकोण में एक समस्या होती है जब विंडो अधिकतम होने पर उपयोगकर्ता एप्लिकेशन को बंद कर देता है।
विनीसियस रोचा

@Vicicius, क्या आप विस्तृत कर सकते हैं? वास्तव में मुद्दा क्या है?
थॉमस लेवेस्क

4
क्या होगा जब लोगों के पास दो मॉनिटर हैं और इस प्रकार इसके नकारात्मक निर्देशांक हो सकते हैं और फिर वे मॉनिटर कॉन्फ़िगरेशन बदलते हैं और मान अब मान्य नहीं हैं?
एंड्रयू ट्रोपल

33

जब आप "अपना खुद का रोल" कर सकते हैं और मैन्युअल रूप से सेटिंग्स को कहीं बचा सकते हैं, और सामान्य तौर पर यह काम करेगा, तो सभी मामलों को सही तरीके से नहीं संभालना बहुत आसान है। यह काफी बेहतर ओएस, आपके लिए काम करने को फोन करके यह बताने के लिए है GetWindowPlacement () बाहर निकलें और पर SetWindowPlacement () स्टार्टअप पर। यह क्रेजी एज के सभी मामलों को संभालता है जो हो सकते हैं (कई मॉनिटर, विंडो के सामान्य आकार को बचा सकते हैं यदि यह अधिकतम होने पर बंद हो जाता है, आदि) ताकि आपको न करना पड़े।

यह MSDN नमूना दिखाता है कि इनका उपयोग WPF ऐप के साथ कैसे किया जाता है। नमूना सही नहीं है (विंडो ऊपरी बाएँ कोने में पहले रन के दौरान जितना संभव हो उतना छोटा हो जाएगा, और सेटिंग्स डिज़ाइनर के साथ कुछ विषम व्यवहार होता है जो कि प्रकार के मूल्य को बचाता है WINDOWPLACEMENT), लेकिन यह कम से कम आपको आरंभ करना चाहिए।


अच्छा समाधान है। हालाँकि मुझे अभी पता चला है कि GetWindowPlacement / SetWindowPlacement एयरो स्नैप जागरूक नहीं
मार्क बेल

1
@RandomEngy ने इसके आधार पर एक बेहतर उत्तर पोस्ट किया है।
स्टीफन गौरिचोन 19:18

27

थॉमस द्वारा ऊपर पोस्ट किए गए "लंबे रूप" बंधन को लगभग कोई कोडिंग की आवश्यकता नहीं है, बस यह सुनिश्चित करें कि आपके पास नाम स्थान बंधन है:

<Window x:Class="WpfApplication1.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:p="clr-namespace:WpfApplication1.Properties"
        Title="Window1"
        Height="{Binding Source={x:Static p:Settings.Default}, Path=Height, Mode=TwoWay}"
        Width="{Binding Source={x:Static p:Settings.Default}, Path=Width, Mode=TwoWay}"
        Left="{Binding Source={x:Static p:Settings.Default}, Path=Left, Mode=TwoWay}"
        Top="{Binding Source={x:Static p:Settings.Default}, Path=Top, Mode=TwoWay}">

फिर कोड-पीछे बचाने के लिए:

private void frmMain_Closed(object sender, EventArgs e)
{
    Properties.Settings.Default.Save();
}

मैंने इस समाधान को चुना, लेकिन केवल सेटिंग्स को बचाया अगर खिड़की की स्थिति सामान्य थी, अन्यथा इसे अधिकतम रूप से अधिकतम मोड से प्राप्त किया जा सकता है
डेविड साइक्स

7
+1 मैंने इसे भी इस्तेमाल किया, @DavidSykes - विंडो स्टेट के लिए एक और सेटिंग जोड़ना काफी अच्छा काम करता है, जैसेWindowState="{Binding Source={x:Static properties:Settings.Default}, Path=WindowState, Mode=TwoWay}"
RobJohnson

@RobJohnson मैंने आपके सुझाव की कोशिश की और इसने बहुत अच्छा काम किया, धन्यवाद।
डेविड साइक्स

4

वैकल्पिक रूप से, आप निम्न दृष्टिकोण को भी पसंद कर सकते हैं ( स्रोत देखें )। अपने प्रोजेक्ट में WindowSettings वर्ग जोड़ें और WindowSettings.Save="True"अपने मुख्य विंडो के शीर्ष लेख में डालें :

<Window x:Class="YOURPROJECT.Views.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Services="clr-namespace:YOURNAMESPACE.Services" 
    Services:WindowSettings.Save="True">

जहां WindowSettings को इस प्रकार परिभाषित किया गया है:

using System;
using System.ComponentModel;
using System.Configuration;
using System.Windows;

namespace YOURNAMESPACE.Services
{
/// <summary>
///   Persists a Window's Size, Location and WindowState to UserScopeSettings
/// </summary>
public class WindowSettings
{
    #region Fields

    /// <summary>
    ///   Register the "Save" attached property and the "OnSaveInvalidated" callback
    /// </summary>
    public static readonly DependencyProperty SaveProperty = DependencyProperty.RegisterAttached("Save", typeof (bool), typeof (WindowSettings), new FrameworkPropertyMetadata(OnSaveInvalidated));

    private readonly Window mWindow;

    private WindowApplicationSettings mWindowApplicationSettings;

    #endregion Fields

    #region Constructors

    public WindowSettings(Window pWindow) { mWindow = pWindow; }

    #endregion Constructors

    #region Properties

    [Browsable(false)] public WindowApplicationSettings Settings {
        get {
            if (mWindowApplicationSettings == null) mWindowApplicationSettings = CreateWindowApplicationSettingsInstance();
            return mWindowApplicationSettings;
        }
    }

    #endregion Properties

    #region Methods

    public static void SetSave(DependencyObject pDependencyObject, bool pEnabled) { pDependencyObject.SetValue(SaveProperty, pEnabled); }

    protected virtual WindowApplicationSettings CreateWindowApplicationSettingsInstance() { return new WindowApplicationSettings(this); }

    /// <summary>
    ///   Load the Window Size Location and State from the settings object
    /// </summary>
    protected virtual void LoadWindowState() {
        Settings.Reload();
        if (Settings.Location != Rect.Empty) {
            mWindow.Left = Settings.Location.Left;
            mWindow.Top = Settings.Location.Top;
            mWindow.Width = Settings.Location.Width;
            mWindow.Height = Settings.Location.Height;
        }
        if (Settings.WindowState != WindowState.Maximized) mWindow.WindowState = Settings.WindowState;
    }

    /// <summary>
    ///   Save the Window Size, Location and State to the settings object
    /// </summary>
    protected virtual void SaveWindowState() {
        Settings.WindowState = mWindow.WindowState;
        Settings.Location = mWindow.RestoreBounds;
        Settings.Save();
    }

    /// <summary>
    ///   Called when Save is changed on an object.
    /// </summary>
    private static void OnSaveInvalidated(DependencyObject pDependencyObject, DependencyPropertyChangedEventArgs pDependencyPropertyChangedEventArgs) {
        var window = pDependencyObject as Window;
        if (window != null)
            if ((bool) pDependencyPropertyChangedEventArgs.NewValue) {
                var settings = new WindowSettings(window);
                settings.Attach();
            }
    }

    private void Attach() {
        if (mWindow != null) {
            mWindow.Closing += WindowClosing;
            mWindow.Initialized += WindowInitialized;
            mWindow.Loaded += WindowLoaded;
        }
    }

    private void WindowClosing(object pSender, CancelEventArgs pCancelEventArgs) { SaveWindowState(); }

    private void WindowInitialized(object pSender, EventArgs pEventArgs) { LoadWindowState(); }

    private void WindowLoaded(object pSender, RoutedEventArgs pRoutedEventArgs) { if (Settings.WindowState == WindowState.Maximized) mWindow.WindowState = Settings.WindowState; }

    #endregion Methods

    #region Nested Types

    public class WindowApplicationSettings : ApplicationSettingsBase
    {
        #region Constructors

        public WindowApplicationSettings(WindowSettings pWindowSettings) { }

        #endregion Constructors

        #region Properties

        [UserScopedSetting] public Rect Location {
            get {
                if (this["Location"] != null) return ((Rect) this["Location"]);
                return Rect.Empty;
            }
            set { this["Location"] = value; }
        }

        [UserScopedSetting] public WindowState WindowState {
            get {
                if (this["WindowState"] != null) return (WindowState) this["WindowState"];
                return WindowState.Normal;
            }
            set { this["WindowState"] = value; }
        }

        #endregion Properties
    }

    #endregion Nested Types
}
}

3

इसे हल करने का डिफ़ॉल्ट तरीका सेटिंग्स फ़ाइलों का उपयोग करना है। सेटिंग्स फ़ाइलों के साथ समस्या यह है कि आपको सभी सेटिंग्स को परिभाषित करना होगा और उस कोड को लिखना होगा जो डेटा को खुद से आगे और पीछे कॉपी करता है। यदि आप का ट्रैक रखने के लिए बहुत सारे गुण हैं तो थकाऊ।

मैंने इसके लिए लाइब्रेरी का उपयोग करने के लिए एक बहुत ही लचीला और बहुत आसान बनाया है, आप बस यह बताएं कि किस ऑब्जेक्ट को ट्रैक करना है और यह बाकी काम करता है। आप इसमें से बकवास को कॉन्फ़िगर कर सकते हैं, भले ही आप चाहें।

लाइब्रेरी को जोत (जीथब) कहा जाता है , यहां एक पुराना कोडप्रोजेक्ट लेख है जिसके बारे में मैंने लिखा था।

यहां बताया गया है कि आप इसका उपयोग किसी विंडो के आकार और स्थान का ट्रैक रखने के लिए कैसे करेंगे:

public MainWindow()
{
    InitializeComponent();

    _stateTracker.Configure(this)
        .IdentifyAs("MyMainWindow")
        .AddProperties(nameof(Height), nameof(Width), nameof(Left), nameof(Top), nameof(WindowState))
        .RegisterPersistTrigger(nameof(Closed))
        .Apply();
}

जोत बनाम सेटिंग्स फाइलें: जोत के साथ काफी कम कोड है, और यह बहुत कम त्रुटि वाला है क्योंकि आपको केवल एक बार प्रत्येक संपत्ति का उल्लेख करने की आवश्यकता है । सेटिंग्स फ़ाइलों के साथ आपको प्रत्येक संपत्ति का 5 बार उल्लेख करने की आवश्यकता होती है : एक बार जब आप स्पष्ट रूप से संपत्ति बनाते हैं और कोड में चार बार अतिरिक्त होते हैं जो मूल्यों को आगे और पीछे कॉपी करते हैं।

भंडारण, क्रमांकन आदि पूरी तरह से विन्यास योग्य हैं। इसके अलावा, जब आईओसी का उपयोग करते हैं, तो आप इसे हुक भी कर सकते हैं ताकि यह सभी वस्तुओं के लिए स्वचालित रूप से ट्रैकिंग को लागू करे जो इसे हल करता है ताकि आपको संपत्ति के लगातार बने रहने के लिए यह करने की आवश्यकता हो कि इस पर एक [ट्रैक करने योग्य] विशेषता है।

मैं यह सब इसलिए लिख रहा हूं क्योंकि मुझे लगता है कि लाइब्रेरी शीर्ष पायदान पर है और मैं इसके बारे में कहना चाहता हूं।


अच्छा लगा, इसके लिए धन्यवाद - मैंने प्रोग्राम के नाम के आधार पर राज्य ट्रैकर को पथ के साथ सेट करने के लिए एक नए वर्ग में आपके कोड स्निपेट का उपयोग किया है। अब से मुझे केवल एक लाइन लिखनी है और सभी विंडो प्रॉपर्टीज को संभालना है
Awesomeness

1

मैंने एक क्विक क्लास लिखी जो ऐसा करती है। यहाँ बताया गया है कि यह कैसे है:

    public MainWindow()
    {
        FormSizeSaver.RegisterForm(this, () => Settings.Default.MainWindowSettings,
                                   s =>
                                   {
                                       Settings.Default.MainWindowSettings = s;
                                       Settings.Default.Save();
                                   });
        InitializeComponent();
        ...

और यहाँ कोड है:

public class FormSizeSaver
{
    private readonly Window window;
    private readonly Func<FormSizeSaverSettings> getSetting;
    private readonly Action<FormSizeSaverSettings> saveSetting;
    private FormSizeSaver(Window window, Func<string> getSetting, Action<string> saveSetting)
    {
        this.window = window;
        this.getSetting = () => FormSizeSaverSettings.FromString(getSetting());
        this.saveSetting = s => saveSetting(s.ToString());

        window.Initialized += InitializedHandler;
        window.StateChanged += StateChangedHandler;
        window.SizeChanged += SizeChangedHandler;
        window.LocationChanged += LocationChangedHandler;
    }

    public static FormSizeSaver RegisterForm(Window window, Func<string> getSetting, Action<string> saveSetting)
    {
        return new FormSizeSaver(window, getSetting, saveSetting);
    }


    private void SizeChangedHandler(object sender, SizeChangedEventArgs e)
    {
        var s = getSetting();
        s.Height = e.NewSize.Height;
        s.Width = e.NewSize.Width;
        saveSetting(s);
    }

    private void StateChangedHandler(object sender, EventArgs e)
    {
        var s = getSetting();
        if (window.WindowState == WindowState.Maximized)
        {
            if (!s.Maximized)
            {
                s.Maximized = true;
                saveSetting(s);
            }
        }
        else if (window.WindowState == WindowState.Normal)
        {
            if (s.Maximized)
            {
                s.Maximized = false;
                saveSetting(s);
            }
        }
    }

    private void InitializedHandler(object sender, EventArgs e)
    {
        var s = getSetting();
        window.WindowState = s.Maximized ? WindowState.Maximized : WindowState.Normal;

        if (s.Height != 0 && s.Width != 0)
        {
            window.Height = s.Height;
            window.Width = s.Width;
            window.WindowStartupLocation = WindowStartupLocation.Manual;
            window.Left = s.XLoc;
            window.Top = s.YLoc;
        }
    }

    private void LocationChangedHandler(object sender, EventArgs e)
    {
        var s = getSetting();
        s.XLoc = window.Left;
        s.YLoc = window.Top;
        saveSetting(s);
    }
}

[Serializable]
internal class FormSizeSaverSettings
{
    public double Height, Width, YLoc, XLoc;
    public bool Maximized;

    public override string ToString()
    {
        using (var ms = new MemoryStream())
        {
            var bf = new BinaryFormatter();
            bf.Serialize(ms, this);
            ms.Position = 0;
            byte[] buffer = new byte[(int)ms.Length];
            ms.Read(buffer, 0, buffer.Length);
            return Convert.ToBase64String(buffer);
        }
    }

    internal static FormSizeSaverSettings FromString(string value)
    {
        try
        {
            using (var ms = new MemoryStream(Convert.FromBase64String(value)))
            {
                var bf = new BinaryFormatter();
                return (FormSizeSaverSettings) bf.Deserialize(ms);
            }
        }
        catch (Exception)
        {
            return new FormSizeSaverSettings();
        }
    }
}

window.Intitialized विंडो होनी चाहिए। देखने के लिए अधिकतर देखें ।tech .blogspot.com
Gleb Sevruk

@Gleb, दोनों काम मुझे लगता है। क्या आपको इनिशियलाइज्ड पर इससे समस्या है?
t

हां, चूंकि अधिकतम विंडो गलत स्क्रीन पर होगी यदि आप केवल इनिशियलाइज्ड इवेंट का उपयोग करते हैं। मैंने क्या किया है और यह काम करने लगता है: अब मैं लोडेड घटना की भी सदस्यता ले रहा हूं। मैं _विंडो चला गया ।indowState = s.aximized? WindowState.Maximized: WindowState.Normal; "लोड" घटना हैंडलर के अंदर लाइन। window.Initialized + = InitializedHandler; window.Loaded + = LoadedHandler; btw: मुझे यह तरीका पसंद है
Gleb Sevruk

1

वहाँ एक है NuGet परियोजना RestoreWindowPlace पर देख GitHub , कि आप के लिए यह सब करता है एक एक्सएमएल फ़ाइल में जानकारी की बचत।

इसे विंडो पर काम करने के लिए, यह कॉलिंग जितना आसान है:

((App)Application.Current).WindowPlace.Register(this);

App में आप अपनी विंडोज़ प्रबंधित करने वाला वर्ग बनाते हैं। अधिक जानकारी के लिए ऊपर github लिंक देखें।


0

आप इसे पसंद कर सकते हैं:

public class WindowStateHelper
{
    public static string ToXml(System.Windows.Window win)
    {
        XElement bounds = new XElement("Bounds");
        if (win.WindowState == System.Windows.WindowState.Maximized)
        {
            bounds.Add(new XElement("Top", win.RestoreBounds.Top));
            bounds.Add(new XElement("Left", win.RestoreBounds.Left));
            bounds.Add(new XElement("Height", win.RestoreBounds.Height));
            bounds.Add(new XElement("Width", win.RestoreBounds.Width));
        }
        else
        {
            bounds.Add(new XElement("Top", win.Top));
            bounds.Add(new XElement("Left", win.Left));
            bounds.Add(new XElement("Height", win.Height));
            bounds.Add(new XElement("Width", win.Width));
        }
        XElement root = new XElement("WindowState",
            new XElement("State", win.WindowState.ToString()),
            new XElement("Visibility", win.Visibility.ToString()),
            bounds);

        return root.ToString();
    }

    public static void FromXml(string xml, System.Windows.Window win)
    {
        try
        {
            XElement root = XElement.Parse(xml);
            string state = root.Descendants("State").FirstOrDefault().Value;
            win.WindowState = (System.Windows.WindowState)Enum.Parse(typeof(System.Windows.WindowState), state);

            state = root.Descendants("Visibility").FirstOrDefault().Value;
            win.Visibility = (System.Windows.Visibility)Enum.Parse(typeof(System.Windows.Visibility), state);

            XElement bounds = root.Descendants("Bounds").FirstOrDefault();
            win.Top = Convert.ToDouble(bounds.Element("Top").Value);
            win.Left = Convert.ToDouble(bounds.Element("Left").Value);
            win.Height = Convert.ToDouble(bounds.Element("Height").Value);
            win.Width = Convert.ToDouble(bounds.Element("Width").Value);
        }
        catch (Exception x)
        {
            System.Console.WriteLine(x.ToString());
        }
    }
}

जब एप्लिकेशन बंद हो जाता है:

        Properties.Settings.Default.Win1Placement = WindowStateHelper.ToXml(win1);
        Properties.Settings.Default.Win2Placement = WindowStateHelper.ToXml(win2);
        ...

जब एप्लिकेशन शुरू होता है:

        WindowStateHelper.FromXml(Properties.Settings.Default.Win1Placement, win1);
        WindowStateHelper.FromXml(Properties.Settings.Default.Win2Placement, win2);
        ...

0

अपनी डिफ़ॉल्ट सेटिंग्स में WindowXml नामक एक स्ट्रिंग बनाएं।

विंडो आकार और स्थान को पुनर्स्थापित करने और सहेजने के लिए अपने विंडो लोडेड और क्लोजिंग ईवेंट पर इस एक्सटेंशन विधि का उपयोग करें।

using YourProject.Properties;
using System;
using System.Linq;
using System.Windows;
using System.Xml.Linq;

namespace YourProject.Extensions
{
    public static class WindowExtensions
    {
        public static void SaveSizeAndLocation(this Window w)
        {
            try
            {
                var s = "<W>";
                s += GetNode("Top", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Top : w.Top);
                s += GetNode("Left", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Left : w.Left);
                s += GetNode("Height", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Height : w.Height);
                s += GetNode("Width", w.WindowState == WindowState.Maximized ? w.RestoreBounds.Width : w.Width);
                s += GetNode("WindowState", w.WindowState);
                s += "</W>";

                Settings.Default.WindowXml = s;
                Settings.Default.Save();
            }
            catch (Exception)
            {
            }
        }

        public static void RestoreSizeAndLocation(this Window w)
        {
            try
            {
                var xd = XDocument.Parse(Settings.Default.WindowXml);
                w.WindowState = (WindowState)Enum.Parse(typeof(WindowState), xd.Descendants("WindowState").FirstOrDefault().Value);
                w.Top = Convert.ToDouble(xd.Descendants("Top").FirstOrDefault().Value);
                w.Left = Convert.ToDouble(xd.Descendants("Left").FirstOrDefault().Value);
                w.Height = Convert.ToDouble(xd.Descendants("Height").FirstOrDefault().Value);
                w.Width = Convert.ToDouble(xd.Descendants("Width").FirstOrDefault().Value);
            }
            catch (Exception)
            {
            }
        }

        private static string GetNode(string name, object value)
        {
            return string.Format("<{0}>{1}</{0}>", name, value);
        }
    }
}

0

मैं लांस क्लीवलैंड से जवाब का उपयोग कर रहा हूं और सेटिंग को बांधता हूं। लेकिन मैं कुछ और कोड का उपयोग कर रहा हूं ताकि मेरी विंडो स्क्रीन से बाहर हो जाए।

private void SetWindowSettingsIntoScreenArea()
{
    // first detect Screen, where we will display the Window
    // second correct bottom and right position
    // then the top and left position.
    // If Size is bigger than current Screen, it's still possible to move and size the Window

    // get the screen to display the window
    var screen = System.Windows.Forms.Screen.FromPoint(new System.Drawing.Point((int)Default.Left, (int)Default.Top));

    // is bottom position out of screen for more than 1/3 Height of Window?
    if (Default.Top + (Default.Height / 3) > screen.WorkingArea.Height)
        Default.Top = screen.WorkingArea.Height - Default.Height;

    // is right position out of screen for more than 1/2 Width of Window?
    if (Default.Left + (Default.Width / 2) > screen.WorkingArea.Width)
        Default.Left = screen.WorkingArea.Width - Default.Width;

    // is top position out of screen?
    if (Default.Top < screen.WorkingArea.Top)
        Default.Top = screen.WorkingArea.Top;

    // is left position out of screen?
    if (Default.Left < screen.WorkingArea.Left)
        Default.Left = screen.WorkingArea.Left;
}

0

मैंने एक और सामान्य समाधान रैंडमाइंग्स के शानदार उत्तर के आधार पर बनाया। यह रनिंग फ़ोल्डर में फ़ाइल करने की स्थिति को बचाता है और आपको अपने द्वारा बनाई गई प्रत्येक नई विंडो के लिए नए गुण बनाने की आवश्यकता नहीं है। मेरे लिए कोड में कम से कम कोड के साथ यह sollution बढ़िया काम करता है।

using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Xml;
using System.Xml.Serialization;

namespace WindowPlacementNameSpace
{

    // RECT structure required by WINDOWPLACEMENT structure
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;

        public RECT(int left, int top, int right, int bottom)
        {
            this.Left = left;
            this.Top = top;
            this.Right = right;
            this.Bottom = bottom;
        }
    }

    // POINT structure required by WINDOWPLACEMENT structure
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
    {
        public int X;
        public int Y;

        public POINT(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }
    }

    // WINDOWPLACEMENT stores the position, size, and state of a window
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct WINDOWPLACEMENT
    {
        public int length;
        public int flags;
        public int showCmd;
        public POINT minPosition;
        public POINT maxPosition;
        public RECT normalPosition;
    }

    public static class WindowPlacement
    {
        private static readonly Encoding Encoding = new UTF8Encoding();
        private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(WINDOWPLACEMENT));

        [DllImport("user32.dll")]
        private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);

        [DllImport("user32.dll")]
        private static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);

        private const int SW_SHOWNORMAL = 1;
        private const int SW_SHOWMINIMIZED = 2;

        private static void SetPlacement(IntPtr windowHandle, string placementXml)
        {
            if (string.IsNullOrEmpty(placementXml))
            {
                return;
            }

            byte[] xmlBytes = Encoding.GetBytes(placementXml);

            try
            {
                WINDOWPLACEMENT placement;
                using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
                {
                    placement = (WINDOWPLACEMENT)Serializer.Deserialize(memoryStream);
                }

                placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
                placement.flags = 0;
                placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
                SetWindowPlacement(windowHandle, ref placement);
            }
            catch (InvalidOperationException)
            {
                // Parsing placement XML failed. Fail silently.
            }
        }

        private static string GetPlacement(IntPtr windowHandle)
        {
            WINDOWPLACEMENT placement;
            GetWindowPlacement(windowHandle, out placement);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8))
                {
                    Serializer.Serialize(xmlTextWriter, placement);
                    byte[] xmlBytes = memoryStream.ToArray();
                    return Encoding.GetString(xmlBytes);
                }
            }
        }
        public static void ApplyPlacement(this Window window)
        {
            var className = window.GetType().Name;
            try
            {
                var pos = File.ReadAllText(Directory + "\\" + className + ".pos");
                SetPlacement(new WindowInteropHelper(window).Handle, pos);
            }
            catch (Exception exception)
            {
                Log.Error("Couldn't read position for " + className, exception);
            }

        }

        public static void SavePlacement(this Window window)
        {
            var className = window.GetType().Name;
            var pos =  GetPlacement(new WindowInteropHelper(window).Handle);
            try
            {
                File.WriteAllText(Directory + "\\" + className + ".pos", pos);
            }
            catch (Exception exception)
            {
                Log.Error("Couldn't write position for " + className, exception);
            }
        }
        private static string Directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

    }
}

आपके पीछे आपके कोड में आप इन दोनों विधियों को जोड़ते हैं

///This method is save the actual position of the window to file "WindowName.pos"
private void ClosingTrigger(object sender, EventArgs e)
{
    this.SavePlacement();
}
///This method is load the actual position of the window from the file
protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    this.ApplyPlacement();
}

xaml विंडो में आप इसे जोड़ते हैं

Closing="ClosingTrigger"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.