WPF Desktop App can Popup multiple full size windows randomly and confuse users. So it is useful to create a list storing these windows and arrange their display as One Full size with all other as thumbnail hanging to the side.The following code implement what is shown in the screen shot. Note this assume one dispatcher due to threading issues. i.e all windows must pop up from on dispatcher.
Code for a window self arrange:
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Reactive.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; namespace WpfApplication1 { /// <summary> /// Interaction logic for Window1.xaml /// </summary> public partial class Window2 : Window { #region declaration public IObservable<System.Reactive.EventPattern<EventArgs>> WindowLocationChangedRxEventArgs { get; set; } public IObservable<System.Reactive.EventPattern<MouseButtonEventArgs>> WindowMouseDownRxEventArgs { get; set; } public IObservable<System.Reactive.EventPattern<MouseEventArgs>> HeaderPreviewMouseMoveRxEventArgs { get; set; } public bool SwitchInProgress { get; set; } public static SortedList<DateTime, Window2> TopWindowList { get; set; } public Guid ID { get; set; } public DateTime AddedAt { get; set; } public static Point LocationOfArrangement { get; set; } #endregion #region Contructor public Window2() { InitializeComponent(); WindowStyle = System.Windows.WindowStyle.None; ResizeMode = System.Windows.ResizeMode.NoResize; ID = Guid.NewGuid(); AddedAt = DateTime.Now; AddToList(); ToolTip = ID.ToString(); #region Event to Rx Observable WindowLocationChangedRxEventArgs = from evt in Observable.FromEventPattern<EventHandler, EventArgs>(h => this.LocationChanged += h, h => this.LocationChanged -= h) select evt; WindowLocationChangedRxEventArgs.Subscribe(evt => { Window2 w = evt.Sender as Window2; if (w.IsFullSize && !w.SwitchInProgress) { LocationOfArrangement = new Point(w.Left, w.Top); w.ArrangeDisplay(); } if (w.SwitchInProgress) w.SwitchInProgress = false; }); WindowMouseDownRxEventArgs = from evt in Observable.FromEventPattern<MouseButtonEventHandler, MouseButtonEventArgs>(h => MouseDown += h, h => MouseDown -= h) select evt; WindowMouseDownRxEventArgs.Subscribe(evt => { Window2 w = evt.Sender as Window2; if (w.IsFullSize) return; SwitchInProgress = true; ArrangeDisplay(true); }); HeaderPreviewMouseMoveRxEventArgs = from evt in Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(h => header.PreviewMouseMove += h, h => header.PreviewMouseMove -= h) select evt; HeaderPreviewMouseMoveRxEventArgs.Subscribe(evt => { if (evt.EventArgs.LeftButton == MouseButtonState.Pressed) { DragMove(); } }); #endregion t1.Text = "Just for Identication: " + ID + " " + AddedAt.ToString(); t2.Text = "Managed Thread Id " + System.Threading.Thread.CurrentThread.ManagedThreadId; } static Window2() { TopWindowList = new SortedList<DateTime, Window2>(); LocationOfArrangement = new Point(300, 300); } #endregion #region List public void RemoveFromListById(Guid id) { var w= TopWindowList.FirstOrDefault(_=>_.Value.ID==id); TopWindowList.Remove(w.Key); } public void AddToList() { Window2 w = (from _ in TopWindowList.Values where _.ID == this.ID select _).FirstOrDefault(); if (w == null) { TopWindowList.Add(AddedAt, this); } } #endregion #region Arrange public void ArrangeDisplay(bool MakeMeFullSize = false) { ArrangeSize(MakeMeFullSize); ArrangeLocaton(); ToggleContent(); } #endregion #region Content public void ShowFullContent() { v.Visibility = System.Windows.Visibility.Collapsed; g.Visibility = System.Windows.Visibility.Visible; } public void ShowSmallContent() { v.Visibility = Visibility.Visible; g.Visibility = System.Windows.Visibility.Collapsed; } private void ToggleContent() { foreach (var t in TopWindowList.Values) { if (t.IsFullSize) t.ShowFullContent(); else t.ShowSmallContent(); } } #endregion #region Location private void ArrangeLocaton() { Window2 prevThumbnail = null; TopWindowList.OrderBy(_ => _.Key); for (int i = 0; i < TopWindowList.Values.Count;i++ ) { var t = TopWindowList.Values[i]; if (t.IsFullSize) { t.Top = LocationOfArrangement.Y; t.Left = LocationOfArrangement.X; } else { if (prevThumbnail == null) { t.Top = LocationOfArrangement.Y; t.Left = LocationOfArrangement.X - t.Width - 2; } else { double d1 = 0; double d2 = 0; d1 = prevThumbnail.Top + prevThumbnail.Height; d2 = prevThumbnail.Left; t.Top = d1 + 2; t.Left = d2; } prevThumbnail = t; } } } #endregion #region Sizing private bool IsFullSize { get; set; } private void ShowFullSize() { ResizeMode = System.Windows. ResizeMode.CanResize; Width = 300; Height = 300; ResizeMode = System.Windows.ResizeMode.NoResize; IsFullSize = true; } private void ShowThumbnailSize() { ResizeMode = System.Windows.ResizeMode.CanResize; Width = 50; Height = 50; ResizeMode = System.Windows.ResizeMode.NoResize; IsFullSize = false; } private void ArrangeSize(bool MakeMeFullSize = false) { if (MakeMeFullSize) foreach (var t in TopWindowList.Values) { if (t.ID == this.ID) t.ShowFullSize(); else t.ShowThumbnailSize(); } else { var q = (from _ in TopWindowList.Values where _.IsFullSize select _).FirstOrDefault(); if (q == null && TopWindowList.Values.Count > 0) { TopWindowList.OrderBy(_ => _.Key); TopWindowList.Values[0].ArrangeDisplay(true); } if(q!=null) { if (q.ID != ID) { ShowThumbnailSize(); } } } } #endregion } }Xaml code
<Window x:Class="WpfApplication1.Window2" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window2" Height="300" Width="300" BorderBrush="Gray" BorderThickness="1" ShowInTaskbar="False"> <Grid> <Grid Name="g"> <Grid.RowDefinitions> <RowDefinition Height="21*"/> <RowDefinition Height="111*"/> <RowDefinition Height="95*"/> <RowDefinition Height="40*"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="150" MinWidth="144"/> <ColumnDefinition Width="150" MinWidth="148"/> </Grid.ColumnDefinitions> <Rectangle Name="header" Fill="Gray" Grid.Row="0" HorizontalAlignment="Left" Height="20" Stroke="Black" VerticalAlignment="Top" Width="292" Grid.Column="0" Grid.ColumnSpan="2" /> <TextBox Name="t1" Height="101" Margin="10,0,18,0" Grid.Row="1" TextWrapping="Wrap" AcceptsReturn="True" Text="TextBox" VerticalAlignment="Top" Grid.Column="0" Grid.ColumnSpan="2"/> <TextBox Name="t2" Height="89" Margin="10,4,18,0" Grid.Row="2" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Grid.Column="0" Grid.ColumnSpan="2"/> <Button Content="Send" Grid.Row="3" Grid.Column="1" Margin="10,4,17,6"/> <Button Content="Close" Grid.Row="3" Grid.Column="0" Margin="10,4,10,6"/> </Grid> <Viewbox Name="v" Visibility="Collapsed" > <StackPanel> <TextBlock TextWrapping="Wrap" >Thumbnail Content </TextBlock> <TextBlock TextWrapping="Wrap" >Small Size Shrinkable</TextBlock> </StackPanel> </Viewbox> </Grid> </Window>Code To Simulate Windows Mutiple PopUp
private void Button_Click(object sender, RoutedEventArgs e) { Observable.Interval(TimeSpan.FromSeconds(3)).Subscribe((t) => { Dispatcher.Invoke(() => { Window2 w = new Window2() { }; w.Show(); w.ArrangeDisplay(); }); }); }
Blog Archive
Thursday, September 26, 2013
Self Arrange Top Windows
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment