.NET WPF সেশনগুলির মধ্যে উইন্ডোর আকার মনে রাখবেন


94

মূলত যখন ব্যবহারকারীরা আমার অ্যাপ্লিকেশনটির উইন্ডোটির আকার পরিবর্তন করে আমি পুনরায় অ্যাপ্লিকেশনটি পুনরায় খোলার সময় অ্যাপ্লিকেশনটি একই আকারের চাই।

প্রথমে আমি যদিও সাইজ চেঞ্জড ইভেন্টটি পরিচালনা করেছি এবং উচ্চতা এবং প্রস্থকে সংরক্ষণ করব তবে আমি মনে করি এর থেকে আরও সহজ সমাধান অবশ্যই হবে।

খুব সহজ সমস্যা, তবে এর সহজ সমাধান আমি খুঁজে পাচ্ছি না।


4
দয়া করে মনে রাখবেন যে আপনি যদি আকার এবং অবস্থান উভয়ই প্রতিরোধ করছেন (নীচে সর্বাধিক কোড নমুনাগুলি হিসাবে), আপনি যে প্রান্ত- কেসটি পরিচালনা করতে চান যেখানে উইন্ডোটি সর্বশেষ উপস্থাপিত হয়েছিল তার মনিটরটি আনপ্লাগ করা হয়েছিল, যাতে আপনার উপস্থাপনা এড়ানো যায় না উইন্ডো অফ স্ক্রিন।
ওমর রাভিভ

@ ওমরআরভিভ আপনি কি এমন নজির খুঁজে পেয়েছেন যা অ্যাকাউন্টে প্রান্ত কেস গ্রহণ করছে?
অ্যান্ড্রু ট্রকল

একটি মন্তব্য যুক্ত করার জন্য আমার কাছে খুব কম প্রত্যাশা রয়েছে, তাই আমি এই নতুন অ্যাঞ্জার তৈরি করেছি। আমি রব জনসনের সেটিং সহ ল্যান্স ক্লিভল্যান্ডের মতো একই সমাধানটি ব্যবহার করি , তবে আপনি যদি এটি সাব উইন্ডোগুলির জন্য ব্যবহার করেন এবং একই সাথে আরও কিছু খুলতে চান তবে এটি কার্যকর হয় না ...
অ্যালানই

উত্তর:


122

User.config ফাইলটিতে মানগুলি সংরক্ষণ করুন।

আপনার সেটিংস ফাইলে মান তৈরি করতে হবে - এটি বৈশিষ্ট্য ফোল্ডারে থাকা উচিত। পাঁচটি মান তৈরি করুন:

  • Top প্রকারের double
  • Left প্রকারের double
  • Height প্রকারের double
  • Width প্রকারের double
  • Maximizedপ্রকারের bool- উইন্ডোটি সর্বাধিক হয় কিনা তা ধরে রাখতে। আপনি যদি আরও তথ্য সঞ্চয় করতে চান তবে অন্য ধরণের বা কাঠামোর প্রয়োজন হবে।

আপনার অ্যাপ্লিকেশনের ডিফল্ট আকারে প্রথম দুটি থেকে 0 এবং দ্বিতীয় দুটি আরম্ভ করুন এবং শেষটি মিথ্যা to

একটি উইন্ডো_অনসোর্সআইনিটায়ালাইজড ইভেন্ট হ্যান্ডলার তৈরি করুন এবং নিম্নলিখিতটি যুক্ত করুন:

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

দ্রষ্টব্য: সেট উইন্ডো প্লেসমেন্টটি উইন্ডোটির উত্স সূচনা ইভেন্টে যেতে হবে যা নির্মাণকারী নয়, অন্যথায় যদি আপনার উইন্ডোটি দ্বিতীয় মনিটরে সর্বাধিক হয় তবে এটি সর্বদা প্রাথমিক মনিটরে পুনরায় চালু হবে এবং আপনি সক্ষম হবেন না এটি অ্যাক্সেস করতে।

একটি উইন্ডো_ সমাপ্ত ইভেন্ট হ্যান্ডলার তৈরি করুন এবং নিম্নলিখিতগুলি যুক্ত করুন:

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

এটি ব্যর্থ হবে যদি ব্যবহারকারী প্রদর্শনের ক্ষেত্রটি ছোট করে তোলে - হয় কোনও স্ক্রিন সংযোগ বিচ্ছিন্ন করে বা স্ক্রিন রেজোলিউশন পরিবর্তন করে - অ্যাপ্লিকেশনটি বন্ধ থাকা অবস্থায় আপনার মান পরীক্ষা করার আগে পছন্দসই অবস্থান এবং আকারটি বৈধ কিনা তা পরীক্ষা করে নেওয়া উচিত।


4
আসলে, স্কোপ "ব্যবহারকারী" সহ সেটিংসগুলি প্রোগ্রাম ফাইলগুলিতে অ্যাপ.config ফাইলে সংরক্ষণ করা হয় না তবে ব্যবহারকারীর অ্যাপ্লিকেশন ডেটা ডিরেক্টরিতে একটি ইউজার.কনফিগ ফাইলে থাকে। সুতরাং এটি কোনও সমস্যা নয় ...
টমাস লেভসেক

7
আসলে আপনি সেটিংসে "উইন্ডোস্টেট" যুক্ত করতে পারেন। প্রকারটি নির্বাচন করুন -> ব্রাউজ করুন -> উপস্থাপনা ফ্রেমওয়ার্ক -> সিস্টেম. উইন্ডো -> উইন্ডোস্টেট :)
মার্টিন ভ্যাসিটিকা

4
এফডাব্লুআইডাব্লু, অ্যাপ্লিকেশন ক্র্যাশের ক্ষেত্রে আমি আকার পরিবর্তিত হ্যান্ডলার থেকেও এটি করি। তারা একটি অযথিত ব্যতিক্রম প্রক্রিয়াজাতকরণের সাথে বিরল, তবে ব্যবহারকারী যখন রহস্যজনকভাবে ঘটে তখন তারা কেন হারিয়ে যাওয়া আকার / অবস্থানের শাস্তি দেয়।
থমাস

7
এই কোডটিতে একটি ত্রুটি রয়েছে, যদি ব্যবহারকারী তার / তার দ্বিতীয় স্ক্রিনে উইন্ডোটি খোলেন, তারপরে কম্পিউটার থেকে সেই স্ক্রিনটি সংযোগ বিচ্ছিন্ন করে দেয়, পরের বার তারা উইন্ডোটি খোলার পরে এটি স্ক্রিনটি উপস্থাপিত হবে। উইন্ডোটি যদি মডেল হয় তবে ব্যবহারকারী অ্যাপটির সাথে মোটেই ইন্টারেক্ট করতে পারবেন না এবং কী চলছে তা বুঝতে পারবেন না। আপনাকে উইন্ডো.গেটস্ক্রিন () ব্যবহার করে স্ক্রিনের স্থানাঙ্কগুলি ডিপিআই নির্ভরশীল মানগুলিতে রূপান্তর করার
ওমর রাভিভ

4
@ ওমররাভিভ - এটি কোনও বাগ নয়, তবে একটি সীমাবদ্ধতা :) সিরিয়াসলি - আমি সমস্যার সেই দিকটি চিহ্নিত করিনি।
ক্রিসএফ

74

আসলে এটি করার জন্য আপনার কোড-ব্যাক ব্যবহার করার দরকার নেই (সেটিংস সংরক্ষণ ব্যতীত)। উইন্ডোর আকার এবং অবস্থানটিকে এই জাতীয় সেটিংসে আবদ্ধ করতে আপনি একটি কাস্টম মার্কআপ এক্সটেনশন ব্যবহার করতে পারেন:

<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 - আমি বাঁধাই এবং এক্সটেনশনের ব্যবহার পছন্দ করি! আপনি যদি আপনার বাউন্ড সেটিংসে উইন্ডোস্টেট যুক্ত করেন তবে এটি সম্পূর্ণ ক্ষমতা সরবরাহ করে। পরিবর্তে আপনি যদি ব্যবহারকারী DataContext পাওয়া সেটিংস আছে, তবে আপনি ভালো কিছু ব্যবহার করতে পারেন {Binding Settings.Height}, ইত্যাদি
ম্যাট DeKrey

উইন্ডোটি সর্বাধিক করা হয় যখন ব্যবহারকারী অ্যাপ্লিকেশনটি বন্ধ করে দেয় তখন এই পদ্ধতির কোনও সমস্যা রয়েছে।
ভিনিসিয়াস রোচা

@ ভিনিসিয়াস, আপনি কি বিস্তারিত বলতে পারবেন? বিষয়টি ঠিক কী?
থমাস লেভেস্ক

4
লোকদের যখন দুটি মনিটর থাকে এবং সুতরাং এটিতে নেতিবাচক স্থানাঙ্ক থাকতে পারে এবং তারপরে তারা মনিটরের কনফিগারেশন পরিবর্তন করে এবং মানগুলি আর কার্যকর হয় না?
অ্যান্ড্রু ট্রকল

33

আপনি "নিজের নিজের রোল" করতে পারেন এবং ম্যানুয়ালি সেটিংসটি কোথাও সংরক্ষণ করতে পারেন এবং সাধারণভাবে এটি কাজ করবে, সমস্ত ক্ষেত্রে সঠিকভাবে পরিচালনা না করা খুব সহজ। এটা অনেক ভালো ওএস, আপনার জন্য কাজ করতে কল করে দেওয়া হয় GetWindowPlacement () প্রস্থান করুন এবং এ SetWindowPlacement () স্টার্টআপে। এটি ঘটতে পারে এমন সমস্ত ক্রেজি প্রান্তগুলি হ্যান্ডল করে (একাধিক মনিটর, উইন্ডোটি সর্বাধিক করার সময় বন্ধ করা থাকলে এটি সংরক্ষণ করুন, ইত্যাদি) যাতে আপনার প্রয়োজন হয় না।

এই এমএসডিএন নমুনাটি কীভাবে ডাব্লুপিএফ অ্যাপ্লিকেশনটি ব্যবহার করে তা দেখায়। নমুনাটি নিখুঁত নয় (উইন্ডোটি প্রথম বামে যতটা সম্ভব ছোট বাম দিকের উপরের কোণায় শুরু হবে, এবং সেটিংস ডিজাইনারের সাথে কিছু ধরণের মান সংরক্ষণের সাথে কিছু অদ্ভুত আচরণ রয়েছে WINDOWPLACEMENT) তবে এটি আপনাকে অন্তত শুরু করা উচিত।


সুন্দর সমাধান। তবে আমি সবেমাত্র আবিষ্কার করেছি যে গেটউইন্ডোপ্লেসমেন্ট / সেট উইন্ডোপ্লেসমেন্ট এয়ারো স্ন্যাপ সচেতন নয়
মার্ক বেল

4
@ র্যান্ডম এঙ্গি এর ভিত্তিতে একটি উন্নত উত্তর পোস্ট করেছে।
স্টাফেন গৌরিচন

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 আমি এটিও ব্যবহার করেছি, @ ডেভিডসাইকস - উইন্ডো স্টেটের জন্য অন্য একটি সেটিংস যুক্ত করা যথেষ্ট ভাল কাজ করছে বলে মনে হয়WindowState="{Binding Source={x:Static properties:Settings.Default}, Path=WindowState, Mode=TwoWay}"
রব জনসন

@ রব জনসন আমি আপনার পরামর্শটি চেষ্টা করেছি এবং এটি খুব ভালভাবে কাজ করেছে, ধন্যবাদ।
ডেভিড সেকস

4

বিকল্পভাবে, আপনি নিম্নলিখিত পদ্ধতিরটিও পছন্দ করতে পারেন ( উত্স দেখুন )। আপনার প্রকল্পে উইন্ডোসেটেটিং ক্লাস যুক্ত করুন 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">

উইন্ডোসেটেটিংগুলি নিম্নলিখিত হিসাবে সংজ্ঞায়িত করা হয়েছে:

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

এটি সমাধানের ডিফল্ট উপায় হ'ল সেটিংস ফাইলগুলি ব্যবহার করা। সেটিংস ফাইলগুলির সমস্যাটি হ'ল আপনাকে সমস্ত সেটিংস সংজ্ঞায়িত করতে হবে এবং কোডটি লিখতে হবে যা ডেটা অনুলিপি করে এবং নিজেকে পিছনে ফেলে দেয়। আপনার ট্র্যাক রাখতে অনেক সম্পত্তি থাকলে বেশ ক্লান্তিযুক্ত।

আমি এটির জন্য একটি খুব নমনীয় এবং খুব সহজে ব্যবহারযোগ্য লাইব্রেরি তৈরি করেছি, আপনি কেবল এটি বলুন কোন বস্তুর কোন বৈশিষ্ট্য ট্র্যাক করা উচিত এবং এটি বাকীটি করে। আপনি যদি চান তবে এটি থেকে ক্রেপও কনফিগার করতে পারেন।

গ্রন্থাগারটিকে জট (গিথুব) বলা হয় , এটি সম্পর্কে আমি লিখেছিলাম একটি পুরানো কোডপ্রজেক্ট নিবন্ধ is

উইন্ডোর আকার এবং অবস্থান সম্পর্কে নজর রাখতে আপনি কীভাবে এটি ব্যবহার করবেন তা এখানে:

public MainWindow()
{
    InitializeComponent();

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

জট বনাম সেটিংস ফাইলগুলি: জোটের সাথে যথেষ্ট কম কোড রয়েছে এবং এটি খুব কম ত্রুটিযুক্ত কারণ আপনার কেবলমাত্র প্রতিটি সম্পত্তি একবার উল্লেখ করা দরকার । সেটিংস ফাইলগুলির সাথে আপনার প্রতিটি সম্পত্তি 5 বার উল্লেখ করতে হবে : একবার আপনি যখন স্পষ্টভাবে সম্পত্তি এবং কোডটিতে অতিরিক্ত চারবার তৈরি করেন যা মানগুলি পিছনে পিছনে নকল করে।

স্টোরেজ, সিরিয়ালাইজেশন ইত্যাদি সম্পূর্ণরূপে কনফিগারযোগ্য। এছাড়াও, আইওসি ব্যবহার করার সময়, আপনি এমনকি এটি হুকও করতে পারেন যাতে এটি সমাধান করা সমস্ত অবজেক্টের জন্য স্বয়ংক্রিয়ভাবে ট্র্যাকিংয়ের প্রয়োগ হয় যাতে সম্পত্তি স্থির করার জন্য আপনার যা করার দরকার তা হ'ল এটিতে একটি [ট্র্যাকযোগ্য] অ্যাট্রিবিউট চাপতে হবে।

আমি এই সমস্ত লিখছি কারণ আমি মনে করি লাইব্রেরিটি শীর্ষ স্থান এবং আমি এটি সম্পর্কে মুখ খুলতে চাই।


ভাল লাগল, এর জন্য ধন্যবাদ - আমি প্রোগ্রামের নামের উপর ভিত্তি করে স্টেট ট্র্যাকার সেট আপ করতে একটি নতুন ক্লাসে আপনার কোড স্নিপেট ব্যবহার করেছি। এখন থেকে আমাকে কেবল একটি লাইন লিখতে হবে এবং সমস্ত উইন্ডো বৈশিষ্ট্যগুলি হ্যান্ডেল করা হবে
অসাধারণতা

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

উইন্ডো.ইন্টিটালাইজড হওয়া উচিত উইন্ডো .লোকডটি দেখুন বেশিরভাগtete.blogspot.com/2008/01/…
গ্লেব সেভ্রুক

@ গ্লেব, দুটোই আমার মনে হয় কাজ করে। আপনি কি ইনিশিয়েটেড এ নিয়ে সমস্যা করছেন?
টিস্টার

হ্যাঁ, যেহেতু সর্বাধিক উইন্ডোটি ভুল স্ক্রিনে থাকবে যদি আপনি কেবল আরম্ভকৃত ইভেন্ট ব্যবহার করেন। আমি যা করেছি এবং এটি কাজ করছে বলে মনে হচ্ছে: এখন আমি লোড ইভেন্টটিতেও সাবস্ক্রাইব করছি। আমি _window.WindowState = s.Maximized এ চলেছি? উইন্ডোস্টেট.ম্যাক্সিমাইজড: উইন্ডোস্টেট.নির্মাল; "লোডেড" ইভেন্ট হ্যান্ডলারের ভিতরে লাইন। window.Initialized + = Usedised হ্যান্ডলার; উইন্ডো.লয়েড + = লোডহ্যান্ডলার; বিটিডব্লিউ: আমি এই পদ্ধতির পছন্দ করি
Gleb Sevruk

1

একটা ব্যাপার NuGet প্রকল্প RestoreWindowPlace দেখতে GitHub , যে আপনার জন্য সব এই আছে একটি XML ফাইলের মধ্যে তথ্য সংরক্ষণ।

এটি একটি উইন্ডোতে কাজ করার জন্য, এটি কল করার মতোই সহজ:

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

অ্যাপে আপনি এমন ক্লাস তৈরি করেন যা আপনার উইন্ডোজ পরিচালনা করে। আরও তথ্যের জন্য উপরের গিথুব লিঙ্কটি দেখুন।


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

আপনার ডিফল্ট সেটিংসে উইন্ডোএক্সএমএল নামের একটি স্ট্রিং তৈরি করুন।

উইন্ডোর আকার এবং অবস্থানটি পুনরুদ্ধার করতে এবং সংরক্ষণ করতে আপনার উইন্ডো লোডড এবং ইভেন্টগুলি বন্ধ করার জন্য এই এক্সটেনশন পদ্ধতিটি ব্যবহার করুন।

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

আমি এলোমেলোভাবে উজ্জ্বল উত্তরের উপর ভিত্তি করে আরও সাধারণ সমাধান করেছি। এটি চলমান ফোল্ডারে ফাইল করার জন্য অবস্থানটি সংরক্ষণ করে এবং আপনার তৈরি প্রতিটি নতুন উইন্ডোর জন্য আপনাকে নতুন বৈশিষ্ট্য তৈরি করার দরকার নেই। এই সলিউশন পিছনে কোডে ন্যূনতম কোড সহ আমার পক্ষে দুর্দান্ত কাজ করে।

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

এক্সএএমএল উইন্ডোতে আপনি এটি যুক্ত করুন

Closing="ClosingTrigger"
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.