Find Visible Child Window - wpf

I want to search any visible child window with this simple code but Message keep saying Window not found. Can anyone has an idea about searching visible child window in main window?
Here's the code:
private HomeWindow NewHomeWindow = new HomeWindow();
string ReturnWindowName;
private void btnhome_Click(object sender, RoutedEventArgs e)
{
ReturnWindowName = "NewHomeWindow";
NewHomeWindow.Owner = this;
NewHomeWindow.Show();
}
private void btnsearchwindow_Click(object sender, RoutedEventArgs e)
{
ChangeWindow();
}
public void ChangeWindow()
{
Window mySearchWindow = (Window)this.FindName(ReturnWindowName);
if (mySearchWindow != null)
{
MessageBox.Show("Window Found");
}
else
{
MessageBox.Show("Window Not Found");
}
}

Since you are assigning ownership to your Windows, can you make use of the OwnedWindows Property to iterate through the Parents Owned Windows to find the one you are looking for? In further looking at your code you are creating a class level variable named NewHomeWindow you are not assigning anything to the Name Property, FindName is searching for a child element, not an owned window. If you add a Name to your Window and use something like this you should be able to locate it.
public partial class MainWindow : Window
{
private HomeWindow NewHomeWindow = new HomeWindow();
string ReturnWindowName;
public MainWindow()
{
InitializeComponent();
NewHomeWindow.Name="NewHomeWindow";
}
private void btnhome_Click(object sender, RoutedEventArgs e)
{
ReturnWindowName = "NewHomeWindow";
NewHomeWindow.Owner = this;
NewHomeWindow.Show();
}
private void btnsearchwindow_Click(object sender, RoutedEventArgs e)
{
ChangeWindow();
}
public void ChangeWindow()
{
foreach (Window w in this.OwnedWindows)
{
if (w.Name == ReturnWindowName)
{
MessageBox.Show("Window Found");
}
else
{
MessageBox.Show("Window Not Found");
}
}
}
}

I'm not entirely sure of your question, but I think you're wanting to find the visual child of a control?
This is a helper function that I use frequently..
public IEnumerable<T> FindVisualChildren<T>( DependencyObject depObj ) where T : DependencyObject
{
if( depObj != null )
{
for( int i = 0; i < VisualTreeHelper.GetChildrenCount( depObj ); i++ )
{
DependencyObject child = VisualTreeHelper.GetChild( depObj, i );
if( child != null && child is T )
{
yield return (T)child;
}
foreach( T childOfChild in FindVisualChildren<T>( child ) )
{
yield return childOfChild;
}
}
}
}
In your example, you'd look for a window:
foreach (var window in FindVisualChildren<Window>(this))
{
if (window.ReturnWindowName == <insertNameHere>)
return window;
}
From there, you can loop through the windows found and match the name.

Related

Close a Window from Another In Wpf

If two Window is opened mainly A and B, how to close Window A using code that written on Window B.
Your best bet would be to create a property on Window B that you pass the creating Window to. Something like this. I have a Window named MainWindow and a second Window named Window2.
Main Window
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Window2 secondForm;
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
secondForm = new Window2();
secondForm.setCreatingForm =this;
secondForm.Show();
}
}
}
Window2
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for Window2.xaml
/// </summary>
public partial class Window2 : Window
{
Window creatingForm;
public Window2()
{
InitializeComponent();
}
public Window setCreatingForm
{
get { return creatingForm; }
set { creatingForm = value; }
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (creatingForm != null)
creatingForm.Close();
}
}
}
In respose to your comment, closing a window that was created by another form is as easy as calling the Close Method of the created Form:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Window2 secondForm;
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
if (secondForm == null)
{
secondForm = new Window2();
secondForm.Show();
}
else
secondForm.Activate();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
if (secondForm != null)
{
secondForm.Close();
secondForm = new Window2();
//How ever you are passing information to the secondWindow
secondForm.Show();
}
}
}
}
Here is a way to close any window from any other window. You can modify it to work with multiple instances by giving your windows some unique identifier and then just searching for that in the foreach loop.
public static class Helper
{
public static void CloseWindowOfWhichThereIsOnlyOne<T>()
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
foreach (Window w in Application.Current.Windows)
{
if (w.GetType().Assembly == currentAssembly && w is T)
{
w.Close();
break;
}
}
}
}
Or with a unique identifier "fudge":
public static void CloseWIndowUsingIdentifier(string windowTag)
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
foreach (Window w in Application.Current.Windows)
{
if (w.GetType().Assembly == currentAssembly && w.Tag.Equals(windowTag))
{
w.Close();
break;
}
}
}
I like this better than the suggested solution because you don't need to mess with your windows, other than to give them unique tags. I've only been using this for small projects where there is no risk of things not being unique, I'm not going to lose track of 10-12 windows!
The other suggested solution is a little silly (I don't have 50 karma to comment on it) as you could just call win.close() if you already had a reference to the object...
it is very simple make one public class and method like this
class Helper
{
public static void CloseWindow(Window x)
{
Assembly currentAssembly = Assembly.GetExecutingAssembly();
// int count = Application.Current.Windows;
foreach (Window w in Application.Current.Windows)
{
//Form f = Application.OpenForms[i];
if (w.GetType().Assembly == currentAssembly && w==x)
{
w.Close();
}
}
}
}
now call this function from where you want close window like this .
Helper.CloseWindow(win);//win is object of window which you want to close.
hope this helps.
foreach (Window w in Application.Current.Windows)
{
if (w.Name != "Main_Window_wind" )
{
w.Visibility = System.Windows.Visibility.Hidden;
}
}
//name is the x:Name="Main_Window_wind" in xaml
You can close now as hiden all windows without closing the named Main_Window_wind , you can add another window to be not closed with this in if: w.Name != "Main_Window_wind" && w.Name != "AnyOther_Window_wind" &&...
a quicker way is this:
for (int intCounter = App.Current.Windows.Count - 1; intCounter > -1; intCounter--)
{
if (App.Current.Windows[intCounter].Name != "Main_Window_wind")
App.Current.Windows[intCounter].Visibility = System.Windows.Visibility.Hidden;
}

Extending a control (ComboBox) in silverlight

I have a simple problem. I am trying to add a dependency property to a combo box. I want to be able to display a value on the face of the combo box when it is initially displayed. There is a ContentPresenter with a TextBlock inside the ComboBox. That TextBlock gets set when a user selects an item in the ComboBox. How can I set that with a default value (not one of the items)? Show something like 'choose one'.
I can extend the ComboBox with a 'DefaultDisplay' dependency property but how do I 'link' that property to the TextBlock that is part of the control template?
Thanks for any help on this.
Pat
Instead of a dependency property I'd suggest using a behavior to do this. I actually already had one of these written for this problem. Give it a try by adding it to your combobox and setting the PromptText property on the behavior:
public class ComboBoxPromptBehavior : Behavior<ComboBox>
{
[Category("Display")]
public string PromptText
{
get { return (string)GetValue(PromptTextProperty); }
set { SetValue(PromptTextProperty, value); }
}
public static readonly DependencyProperty PromptTextProperty = DependencyProperty.Register("PromptText", typeof(string), typeof(ComboBoxPromptBehavior), new PropertyMetadata(" "));
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += new RoutedEventHandler(AssociatedObject_Loaded);
AssociatedObject.LayoutUpdated += new EventHandler(AssociatedObject_LayoutUpdated);
}
void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
{
SetPromptText();
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.Loaded -= new RoutedEventHandler(AssociatedObject_Loaded);
AssociatedObject.LayoutUpdated -= new EventHandler(AssociatedObject_LayoutUpdated);
}
void AssociatedObject_Loaded(object sender, RoutedEventArgs e)
{
SetPromptText();
}
private void SetPromptText()
{
var textbox = AssociatedObject.FindChild<TextBlock>();
if (textbox != null && string.IsNullOrWhiteSpace(textbox.Text))
{
textbox.Text = PromptText;
}
}
}
And the extension method for FindChild is:
public static T FindChild<T>(this DependencyObject element) where T : DependencyObject
{
var childCount = VisualTreeHelper.GetChildrenCount(element);
for (int i = 0; i < childCount; i++)
{
var child = VisualTreeHelper.GetChild(element, i);
if (child is T)
{
return (T)child;
}
var match = child.FindChild<T>();
if (match != null) return match;
}
return null;
}

raising event in a usercontrol from another usercontrol

How to raise a event in usercontrol from the another usercontrol. i tried to do with delegates, but it doesnt work. How can i do this. am using C#(WPF)
usercontrol1.cs
public partial class UserControl1 : UserControl
{
delegate void myDelegate();
public UserControl1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
UserControl2 obj = new UserControl2();
myDelegate d = new myDelegate(obj.CallDelegate);
obj.CallDelegate();
}
}
Usercontrol2.cs
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
}
public void CallDelegate()
{
this.Width = 50;
this.Height = 50;
MessageBox.Show("Method called ");
}
}
when i use delegate i can go get the messagebox from the method, but the control doesnt resize. do i want to render it again ?? i have tried to assign explicitly, but doesnt work
In general, only the event owner can raise an event. There are exceptions to this (such as with Button.PerformClick in Windows Forms, but they have to be specifically provided by the class in question.
It's possible that WPF routed events may give an alternative here, but you haven't been clear about what kind of events you're talking about. An example of what you're trying to do would be helpful.
that's because in your code you raise an event on a new UserControl2. for your specific example the code of the UserControl1.button1_Click event should be like this:
private void button1_Click(object sender, RoutedEventArgs e)
{
if (this.Parent != null && this.Parent is StackPanel)
{
StackPanel parentControl = this.Parent as StackPanel;
foreach (UIElement child in parentControl.Children)
{
if (child is UserControl2)
((UserControl2)child).CallDelegate();
}
}
}
EDIT:
kay so it seems you want to get all the usercontrol2 within the window1 to be resized. then what you need is to make a recursive function to get the topmost parent, e.g (modded from hardcodet.net/2008/02/find-wpf-parent)
DependencyObject GetHighestParent(DependencyObject child)
{
ContentElement contentElement = child as ContentElement;
if (contentElement != null)
{
DependencyObject parent = ContentOperations.GetParent(contentElement);
if (parent != null) return parent;
FrameworkContentElement fce = contentElement as FrameworkContentElement;
return fce != null ? fce.Parent : null;
}
FrameworkElement frameworkElement = child as FrameworkElement;
if (frameworkElement != null)
{
DependencyObject parent = frameworkElement.Parent;
if (parent != null)
{
return GetHighestParent(parent);
}
else
{
return child;
}
}
DependencyObject visualParent = VisualTreeHelper.GetParent(child);
if (visualParent != null)
return GetHighestParent(visualParent);
else
return child;
}
then you might want to create a method to walkdown all the children like this:
void CallDelegateInAllControl2(DependencyObject parent)
{
int childCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is UserControl2)
{
((UserControl2)child).CallDelegate();
}
else
{
CallDelegateInAllControl2(child);
}
}
}
and then you call it within button1_click event
private void button1_Click(object sender, RoutedEventArgs e)
{
DependencyObject parent = GetHighestParent(this);
if(parent!=null)
CallDelegateInAllControl2(parent);
}
note: a walk to get parent and child might be tricky and risky i think and i believe it's a long process so you might just want to re-layout your window1 so it has a StackPanel/Grid with a usercontrol1 element and all usercontrol2 elements within it so you can use the first code i post.

Disable right click "Silverlight" popup in comboboxes

Hi
I'm trying to get rid of the annoying "About Silverlight" context menu that pops up whenever you right click in a Silverlight application. I've added the usual ways:
In App.xaml
rootVisual.MouseRightButtonDown += ((s, args) => args.Handled = true);
and the same for all ChildWindows.
The problem that persist is in all "pop up"-controls like comboboxes and datepicker calender popup. There I can't get rid of it. I would like to handle the right click in a style that I can make implicit for the entire application. Is this possible? Can I solve it some other smart way?
Best
Daniel
The answer was to inherit the combobox and make a custom control like this:
public class CellaComboBox : ComboBox
{
public CellaComboBox()
{
DropDownOpened += _dropDownOpened;
DropDownClosed += _dropDownClosed;
}
private static void _dropDownClosed(object sender, EventArgs e)
{
HandlePopupRightClick(sender, false);
}
private static void _dropDownOpened(object sender, EventArgs e)
{
HandlePopupRightClick(sender, true);
}
private static void HandlePopupRightClick(object sender, bool hook)
{
ComboBox box = (ComboBox)sender;
var popup = box.GetChildElement<Popup>();
if (popup != null)
{
HookPopupEvent(hook, popup);
}
}
static void HookPopupEvent(bool hook, Popup popup)
{
if (hook)
{
popup.MouseRightButtonDown += popup_MouseRightButtonDown;
popup.Child.MouseRightButtonDown += popup_MouseRightButtonDown;
}
else
{
popup.MouseRightButtonDown -= popup_MouseRightButtonDown;
popup.Child.MouseRightButtonDown -= popup_MouseRightButtonDown;
}
}
static void popup_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
e.Handled = true;
}
with the extension method for framworkelement looking like this:
public static class FrameworkElementExtensions
{
public static TType GetChildElement<TType>(this DependencyObject parent) where TType : DependencyObject
{
TType result = default(TType);
if (parent != null)
{
result = parent as TType;
if (result == null)
{
for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); ++childIndex)
{
var child = VisualTreeHelper.GetChild(parent, childIndex) as FrameworkElement;
result = GetChildElement<TType>(child) as TType;
if (result != null) return result;
}
}
}
return result;
}
}
You need to handle the DatePicker in the same way but instead of DropDownOpened and DropDownClosed you use CalenderOpened and CalenderClosed
C# Corner has an article for fixing the about popup on Silverlight 3:
Disable Context Menu in Silverlight 3 Application

Adding button into a Listview in WinForms

Is there a way to add a button control to a cell in inside a ListView in a WinForms app?
Here is a code of a class ListViewExtender that you can reuse. It's not a derived class of ListView, basically you just declare that a specific column is displayed as buttons instead of text. The button's text is the subItem's text.
It allows big sized list views without problems, does not use p/invoke, and also works with horizontal scrollbars (some code proposed as answers here don't or are quite slow with a great number of items). Note it requires the extended ListView to have FullRowSelect set to true and view type set to Details.
This is a sample code that uses it:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent(); // you need to add a listView named listView1 with the designer
listView1.FullRowSelect = true;
ListViewExtender extender = new ListViewExtender(listView1);
// extend 2nd column
ListViewButtonColumn buttonAction = new ListViewButtonColumn(1);
buttonAction.Click += OnButtonActionClick;
buttonAction.FixedWidth = true;
extender.AddColumn(buttonAction);
for (int i = 0; i < 10000; i++)
{
ListViewItem item = listView1.Items.Add("item" + i);
item.SubItems.Add("button " + i);
}
}
private void OnButtonActionClick(object sender, ListViewColumnMouseEventArgs e)
{
MessageBox.Show(this, #"you clicked " + e.SubItem.Text);
}
}
}
Here is the ListViewExtender code and associated classes:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace WindowsFormsApplication1
{
public class ListViewExtender : IDisposable
{
private readonly Dictionary<int, ListViewColumn> _columns = new Dictionary<int, ListViewColumn>();
public ListViewExtender(ListView listView)
{
if (listView == null)
throw new ArgumentNullException("listView");
if (listView.View != View.Details)
throw new ArgumentException(null, "listView");
ListView = listView;
ListView.OwnerDraw = true;
ListView.DrawItem += OnDrawItem;
ListView.DrawSubItem += OnDrawSubItem;
ListView.DrawColumnHeader += OnDrawColumnHeader;
ListView.MouseMove += OnMouseMove;
ListView.MouseClick += OnMouseClick;
Font = new Font(ListView.Font.FontFamily, ListView.Font.Size - 2);
}
public virtual Font Font { get; private set; }
public ListView ListView { get; private set; }
protected virtual void OnMouseClick(object sender, MouseEventArgs e)
{
ListViewItem item;
ListViewItem.ListViewSubItem sub;
ListViewColumn column = GetColumnAt(e.X, e.Y, out item, out sub);
if (column != null)
{
column.MouseClick(e, item, sub);
}
}
public ListViewColumn GetColumnAt(int x, int y, out ListViewItem item, out ListViewItem.ListViewSubItem subItem)
{
subItem = null;
item = ListView.GetItemAt(x, y);
if (item == null)
return null;
subItem = item.GetSubItemAt(x, y);
if (subItem == null)
return null;
for (int i = 0; i < item.SubItems.Count; i++)
{
if (item.SubItems[i] == subItem)
return GetColumn(i);
}
return null;
}
protected virtual void OnMouseMove(object sender, MouseEventArgs e)
{
ListViewItem item;
ListViewItem.ListViewSubItem sub;
ListViewColumn column = GetColumnAt(e.X, e.Y, out item, out sub);
if (column != null)
{
column.Invalidate(item, sub);
return;
}
if (item != null)
{
ListView.Invalidate(item.Bounds);
}
}
protected virtual void OnDrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
e.DrawDefault = true;
}
protected virtual void OnDrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
ListViewColumn column = GetColumn(e.ColumnIndex);
if (column == null)
{
e.DrawDefault = true;
return;
}
column.Draw(e);
}
protected virtual void OnDrawItem(object sender, DrawListViewItemEventArgs e)
{
// do nothing
}
public void AddColumn(ListViewColumn column)
{
if (column == null)
throw new ArgumentNullException("column");
column.Extender = this;
_columns[column.ColumnIndex] = column;
}
public ListViewColumn GetColumn(int index)
{
ListViewColumn column;
return _columns.TryGetValue(index, out column) ? column : null;
}
public IEnumerable<ListViewColumn> Columns
{
get
{
return _columns.Values;
}
}
public virtual void Dispose()
{
if (Font != null)
{
Font.Dispose();
Font = null;
}
}
}
public abstract class ListViewColumn
{
public event EventHandler<ListViewColumnMouseEventArgs> Click;
protected ListViewColumn(int columnIndex)
{
if (columnIndex < 0)
throw new ArgumentException(null, "columnIndex");
ColumnIndex = columnIndex;
}
public virtual ListViewExtender Extender { get; protected internal set; }
public int ColumnIndex { get; private set; }
public virtual Font Font
{
get
{
return Extender == null ? null : Extender.Font;
}
}
public ListView ListView
{
get
{
return Extender == null ? null : Extender.ListView;
}
}
public abstract void Draw(DrawListViewSubItemEventArgs e);
public virtual void MouseClick(MouseEventArgs e, ListViewItem item, ListViewItem.ListViewSubItem subItem)
{
if (Click != null)
{
Click(this, new ListViewColumnMouseEventArgs(e, item, subItem));
}
}
public virtual void Invalidate(ListViewItem item, ListViewItem.ListViewSubItem subItem)
{
if (Extender != null)
{
Extender.ListView.Invalidate(subItem.Bounds);
}
}
}
public class ListViewColumnMouseEventArgs : MouseEventArgs
{
public ListViewColumnMouseEventArgs(MouseEventArgs e, ListViewItem item, ListViewItem.ListViewSubItem subItem)
: base(e.Button, e.Clicks, e.X, e.Y, e.Delta)
{
Item = item;
SubItem = subItem;
}
public ListViewItem Item { get; private set; }
public ListViewItem.ListViewSubItem SubItem { get; private set; }
}
public class ListViewButtonColumn : ListViewColumn
{
private Rectangle _hot = Rectangle.Empty;
public ListViewButtonColumn(int columnIndex)
: base(columnIndex)
{
}
public bool FixedWidth { get; set; }
public bool DrawIfEmpty { get; set; }
public override ListViewExtender Extender
{
get
{
return base.Extender;
}
protected internal set
{
base.Extender = value;
if (FixedWidth)
{
base.Extender.ListView.ColumnWidthChanging += OnColumnWidthChanging;
}
}
}
protected virtual void OnColumnWidthChanging(object sender, ColumnWidthChangingEventArgs e)
{
if (e.ColumnIndex == ColumnIndex)
{
e.Cancel = true;
e.NewWidth = ListView.Columns[e.ColumnIndex].Width;
}
}
public override void Draw(DrawListViewSubItemEventArgs e)
{
if (_hot != Rectangle.Empty)
{
if (_hot != e.Bounds)
{
ListView.Invalidate(_hot);
_hot = Rectangle.Empty;
}
}
if ((!DrawIfEmpty) && (string.IsNullOrEmpty(e.SubItem.Text)))
return;
Point mouse = e.Item.ListView.PointToClient(Control.MousePosition);
if ((ListView.GetItemAt(mouse.X, mouse.Y) == e.Item) && (e.Item.GetSubItemAt(mouse.X, mouse.Y) == e.SubItem))
{
ButtonRenderer.DrawButton(e.Graphics, e.Bounds, e.SubItem.Text, Font, true, PushButtonState.Hot);
_hot = e.Bounds;
}
else
{
ButtonRenderer.DrawButton(e.Graphics, e.Bounds, e.SubItem.Text, Font, false, PushButtonState.Default);
}
}
}
}
The ListView itself (or ListViewItem) does not function as a container of any kind so no way to add controls directly, however it is doable. I have used this extended ListView with a lot of success: Embedding Controls in a ListView.
This is the BEST custom listview control for WinForms.
ObjectListView
To make the extender of Simon Mourier working is missing the following line:
extender.AddColumn(buttonAction);
This is, it should look like:
ListViewExtender extender = new ListViewExtender(listSummary);
ListViewButtonColumn buttonAction = new ListViewButtonColumn(2);
buttonAction.Click += OnButtonActionClick;
buttonAction.FixedWidth = true;
extender.AddColumn(buttonAction);
Maybe this could be of interest?
http://www.codeproject.com/KB/list/extendedlistviews.aspx
No, a standard Windows Forms ListView doesn't support embedded controls. You could try to build your own custom control, or you could use something like http://www.codeproject.com/KB/list/EXListView.aspx.
No and yes, ListView itself does not support such functionality, but you can create a button on top of it, so that it appears to the user as integral part of the listview. (I suppose this is what the ExtendedListView mentioned above does too).
Maybe it worths mentioning, the list view control might be designed in WPF as an usercontrol/custom control with buttons in its ListViewItems, and then use this control in the WinForms application, in an ElementHost control.
I accidentally come across a discussion before, hope this help: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/ee232cc4-68c5-4ed3-9ea7-d4d999956504/
You could use a GlacialList. It allow you to put ANY control inside a list cell and it's simple to use. You will just need to join a GlacialList.dll document to the reference part of your Solution. If you click the link it will show you how it works and how to use it and download it.
If you have a System.IO.FileNotFoundException on the InitializeComponent() just download source code from the above link, compile and use this .dll (inside bin/Debug subfolder) to your project .
Here is an example of what it looks like:
This looks like the simplest answer I have come across... just added an ItemCommand to the ListView.
See this link: handle-the-button-click-event-from-an-asp-net-listview-control

Resources