I created a user control in a project that consists of just a MainWindow.xaml and the code behind. I added the .dll to the toolbox of VS, and dropped it onto a window in a new project. This created the following:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication5"
xmlns:ThinkGeoClean="clr-namespace:ThinkGeoClean;assembly=ThinkGeoClean" x:Class="WpfApplication5.MainWindow"
mc:Ignorable="d"
Title="MainWindow" >
<Grid>
<ThinkGeoClean:ListBoxCustom x:Name="listBoxCustom" />
</Grid>
</Window>
The ThinkGeoClean is the name of the .dll I added which is the usercontrol. ListBoxCustom is just a public class in the control, but is NOT what I want to show. I want to show the main window of the usercontrol (not a window), but it doesn't show as an option after typing <ThinkGeoClean:. The only thing that shows up is ListBoxCustom. If I go ahead and type <ThinkGeoClean.MainWindow>, it gives a XamlParseException error on that line.
Now, if I go into the code-behind and do:
ThinkGeoClean.MainWindow newWin = new ThinkGeoClean.MainWindow();
newWin.Show();
It will pop up the usercontrol in a new window and it works fine.
Here's the beginning of usercontrol code behind:
namespace ThinkGeoClean
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, INotifyPropertyChanged
{
And the xaml for it is just a single grid containing some buttons and a map control.
Edit: In addition to the answer below, my user control was originally just a normal WPF project. I thought changing the output type to a class library would change it into a user control automatically, but I actually had to go into the xaml and change the the into .
This XAML:
<Grid>
<ThinkGeoClean:ListBoxCustom x:Name="listBoxCustom" />
</Grid>
...is not equivalent to creating an instance of a window and call the Show() method on it programmatically.
Instead the XAML processor will try to add the window to the Children collection of the Grid and this is not possible since a window cannot be child of another control. That's why you get an exception.
Also, a UserControl must be hosted in a window or page. It is not a top-level control that you can display without any parent host.
Related
So iv looked around for a bit and found out that MDI is obselete for WPF, Basically what i am trying to do is show a specific page in a grid object on load, and once a menu item from my drop down menu is selected, the content of the grid will be changed to the content from a different page (this is depending on which menu item is selected).
To go into more detail (perhaps this will help) The area where the window will be shown will need to have the window with no borders, or titles, or buttons to minimize/close etc.. only showing the content of this window, it won't be resizeable but fixed, i have a menu of which as i said earlier, when a different menu item is clicked, the relevant window should be displayed in the fixed area. Additionally if any buttons or events inside this content that is displayed happen (i.e a button causes a different window to show for example) then the content in the fixed area should be replaced by this new window's content
This is the first time i have done something like this and from what i've read it sounds like this is something very tricky for a WPF application, I hope i can get some sort of insight or direction i should be going so that i can make this possible.
Thanks.
You can try for example ChildWindow from Extended WPF Toolkit Community Edition.
Edit #1:
But whenever i try to create a WindowContainer in the Xaml it has
problems with the namespace prefix with "xctk:WindowContainer" so
how do i create the appropriate namespace prefix to use it?
You have to add that namespace:
xmlns:xctk=http://schemas.xceed.com/wpf/xaml/toolkit
For example:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Title="MainWindow" Height="350" Width="525">
<Grid>
<xctk:WindowContainer>
<xctk:ChildWindow Height="100" Width="250" Left="10" Top="10">
<TextBlock Text="Hello World ..." />
</xctk:ChildWindow>
</xctk:WindowContainer>
</Grid>
</Window>
Edit #2:
You can of course change some properties (for example):
<xctk:ChildWindow
Height="100"
Width="250"
Left="10"
Top="10"
Name="chWindow"
CloseButtonVisibility="Hidden"
WindowStyle="None"
BorderThickness="0">
Edit #3:
Ok yeah, so with everything referenced it is giving me errors still..
Try it simpleā¦ Create Wpf Application, add Extended WPF Toolkit 2.4 NuGet package, in MainWindow.xaml add previous code and in MainWindow.xaml.cs add next code:
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.chWindow.Show();
}
}
}
I have a tab control that is dynamically populated with tabs that contain user controls of various sizes. When a tab is opened I want the window to automatically resize to a size that makes sense given the active user control. Is there a clean way to do this?
I'm using a standard mvvm pattern.
Use the SizeToContent property on the Window class.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
SizeToContent='Width'>
<Grid>
<Button Width='200' Content='The Button' />
</Grid>
</Window>
I have a storyboard animation in a popup and I want this to be on every page in the application. How can I do this without copy pasting the animation into every XAML and all the code-behind logic to control the animation. I also have buttons that should be on every page as well in certain positions. Is there a better way to do this than duplicating code? I'm already inheriting from PhoneApplicationPage but that only handles the code-behind stuff and no the XAML layout.
You can create UserControl for your animation rather than duplicating code, call this User Control in other user controls or pages.
To add User Control right click your project Add then New Item then Silverlight User Control, name your control accordingly for example "AnimationUserControl" finally click Add. Do your animation work in this new User Control to call this new User Control in other Controls you have to add reference of you project into User Control where u are calling AnimationUserControl for example in MainPage.xaml like this:
<UserControl x:Class="Com.Softechww.Controls.Silverlight.Scheduler.Scheduler"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ProjectNameSpace" Width="800" Height="450" >
add new line with "xmlns:local" which value is referring you projects root, project namespace can be found by right clicking project file in Visual Studio under Silverlight then Default namespace.
now simply call it below in User Control like this:
<Grid x:Name="LayoutRoot">
<local:AnimationUserControl/>
</Grid>
It should work.
I have created a user control in wpf. I have also create a mainwindow. Now, what i want is that, when i click on a button (which is in mainWindow), a user control is shown like a dialog box. suppose i have a button named i-e create new user. Now, what i want is to show the control (that i have created for new user) on button click whithout calling it in mainWindow.
In the WPF demo application Family Show, user controls are created in the main window (MainWindow.xaml)
<!-- New User Control -->
<local:NewUserControl x:Name="NewUserControl"
HorizontalAlignment="Center" VerticalAlignment="Center"
AddButtonClick="NewUserControl_AddButtonClick"/>
Then in the code behind (MainWindow.xaml.cs), the different user controls are hidden or shown as a result of click actions from the button.
/// <summary>
/// Hides the New User Control.
/// </summary>
private void HideNewUserControl()
{
NewUserControl.Visibility = Visibility.Hidden;
DiagramControl.Visibility = Visibility.Visible;
enableButtons();
if (family.Current != null)
DetailsControl.DataContext = family.Current;
}
/// <summary>
/// Shows the New User Control.
/// </summary>
private void ShowNewUserControl()
{
HideFamilyDataControl();
HideDetailsPane();
DiagramControl.Visibility = Visibility.Collapsed;
WelcomeUserControl.Visibility = Visibility.Collapsed;
if (PersonInfoControl.Visibility == Visibility.Visible)
((Storyboard)this.Resources["HidePersonInfo"]).Begin(this);
NewUserControl.Visibility = Visibility.Visible;
NewUserControl.ClearInputFields();
NewUserControl.SetDefaultFocus();
... //Removed for brevity
}
I encourage you to download the Family Show app to look at the source code, or to browse it at least on-line.
You could put it in a separate window like Johannes Hofmeister suggested with his answer.
The main advantage of a User Control is that this user interface block might be used at multiple points in an application. (eg. a graph control user control with scroll, zoom and screenshot buttons would appear next to every graph, making it an ideal candidate for a user control).
You can easily add another window with the your usercontrol on it!
First, create another window (right click in the solution explorer, add new item, Window).
Second, drag you usercontrol onto the window:
<Window x:Class="MyWpfApplication.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:DeleteMeTest="clr-namespace:DeleteMeTest"
Title="Window1" Height="300" Width="300">
<Grid>
<MyWpfApplication:UserControl1 />
</Grid>
</Window>
Then you must setup the button click handler to show the window:
MainWindow.xaml:
<Window x:Class="MyWpfApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Click Me" Click="Button_Click"/>
</Grid>
</Window>
The Button_Click Handler in MainWindow.xaml.cs:
private void Button_Click(object sender, RoutedEventArgs e)
{
new Window1().ShowDialog();
}
The ShowDialog() Method opens a dialog, which means that the window comes on top and must be interacted with (Closed) before you can return to interacting with your main window.
You can also use the Show Method, to have a non blocking window.
I'm new in WPF and C#. I know a lot of VB.NET and I'm used to the way when I call a form object like textboxes, etc. I'm calling it from another form. Now, I'm using WPF, I'm confused. Because I have a Main Window. And I want to add and item to a listbox in the Main Window from a Class. In VB.Net , its just like this.
IN FORM2
Form1.Textbox.Text = "";
Wherein I can't do it in WPF. Can someone please Help me. Thanks!
WPF windows defined in XAML have their controls publicly accessible from other classes and forms, unless you specifically mark them with the x:FieldModifier attribute as private.
Therefore, if you make an instance of your main window accessible in another class, be it a Window or anything else, you'll be able to populate controls from within this second class.
A particular scenario is when you want to update the contents of a control in your main window from a child window that you have opened on top of it. Is such a case, you may set the child window's Owner property to the current, main window, in order to access it while the child is visible. For instance, let's say you have defined these two windows:
// MainWindow
<Window x:Class="TestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListBox Name="mainListBox" Height="250" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
<Button Content="Open Another Window" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="20" Click="OpenAnotherWindow_Click"/>
</Grid>
</Window>
and
// AnotherWindow
<Window x:Class="TestApplication.AnotherWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AnotherWindow" Height="300" Width="300">
<Grid>
<Button Content="Add New Item to Main Window" HorizontalAlignment="Center" VerticalAlignment="Center" Click="AddNewItem_Click"/>
</Grid>
</Window>
each in its own XAML file.
In MainWindow's code behind, inside the button click handler, you show an instance of AnotherWindow as a dialog and set its Owner property to MainWindow's instance:
private void OpenAnotherWindow_Click(object sender, RoutedEventArgs e)
{
AnotherWindow anotherWindow = new AnotherWindow();
anotherWindow.Owner = this;
anotherWindow.ShowDialog();
}
Now, you can access the MainWindow's instance from AnotherWindow's Owner property, in order to add a new item to the ListBox control defined on it, in the button click handler in AnotherWindow's code behind:
private void AddNewItem_Click(object sender, RoutedEventArgs e)
{
MainWindow mainWindow = Owner as MainWindow;
mainWindow.mainListBox.Items.Add(new Random().Next(1000).ToString());
}
It simply adds a new random number to the ListBox, in order to show how the code accesses and modifies the control's data in MainWindow.
Pure WPF solution, but also may be easiest in your case, is using a Data Binding in WPF.
Every form's control is binded to some data on ModelView (pure MVVM approach) or to data (more or less like yuo can do it in WindowsForms). So the "only" thing you have to do is to read/write data binded to controls on UI of that form.
For example, you have TextBox on Windows and want to read a data from it.
This TextBox is binded to some string property of the class that is responsible for holding the data for the controls on that form (just an example, in real world could be 1000 other solutions, based on developer decisions). So what you need, is not to say: "window give textbox" and after read TextBox's content, but simply read binded string property.
Sure it's very simply description of a stuff. But just to give you a hint. Follow databinding link provided above to learn more about this stuff. Do not afraid of a lot of stuff there, it's after all is not a complicated idea and also pretty intuitive. To make that stuff to work in simply case you will not need to make huge efforts by me. The stuff becomes really complex when you end up into real world applications.
This will get all active windows:
foreach (Window item in Application.Current.Windows)
{
}