I have WPF window code and I want to change the window title, normally i can do
this.Title = "Bla"
But what if in xaml part of the window code, I have a text box named Title (Name="Title") which overrides the default window Title variable which sets the title of the window? How do I access the original window title variable without having to rename the textbox?
First solution.
You can use base keyword:
base.Title = "bla";
Second solution.
You can change window title in the Loaded event, by casting sender object to Window.
XAML:
<Window x:Class="WpfWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="title" Height="350" Width="525"
Loaded="Window_Loaded">
<Grid>
<TextBox Name="Title" MinWidth="100" />
</Grid>
</Window>
Code-behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
(sender as Window).Title = "bla";
}
}
Related
I've two windows: Main Window, Log Window. How can I update the listbox in the Log Window when some action is happened in the Main Window (e.g. button is clicked)?
Below is the code for listbox in Log Window:
<ListBox x:Name="DebugLogLb" BorderBrush="{x:Null}">
<TextBlock x:Name="DebugLogTb" Text="{Binding LogText}" Background="{x:Null}" />
</ListBox>
When the button in the Main Window is clicked, it will update the listbox. I tried with the code below but it doesn't work.
private void Btn1_Click(object sender, RoutedEventArgs e)
{
var log = new LogWindow();
log.DebugLogLb.Items.Add(new { LogText = "Button 1 is clicked" });
}
I'm able to update the listbox if I put everything in the same window, but I failed to do so with two windows.
My expected output would be like:
Even if both windows are opened, when the buttons in the Main Window are clicked, it will directly update in the Log Window as well.
Thanks for any helps in advanced.
It's hard to tell where you are going wrong without seeing more of the code. This is an example that works. It creates a new LogWindow in the MainWindow ctor and sets the DataContext. When the button is clicked the handler calls show on the window. The ListBox's itemssource property is bound to an ObservableCollection of strings. So any adds/removes are automatically updated on the UI.
LogWindows xaml
<Window x:Class="WpfApplication7.LogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="LogWindow" Height="300" Width="300">
<Grid>
<ListBox x:Name="DebugLogLb" BorderBrush="{x:Null}" ItemsSource="{Binding LogText}" />
</Grid>
MainWindow code-behind
public partial class MainWindow : Window
{
LogWindow _logWindow;
public MainWindow()
{
InitializeComponent();
LogText = new ObservableCollection<string>();
_logWindow = new LogWindow();
_logWindow.DataContext = this;
_logWindow.Closed += _logWindow_Closed;
}
private void _logWindow_Closed(object sender, EventArgs e)
{
_logWindow = new LogWindow();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
_logWindow.Show();
LogText.Add("Button1 Clicked");
}
public ObservableCollection<string> LogText { get; set; }
}
I created a "WPF Application Project" in Visual Studio 2013.
I opened the "MainWindow.xaml" file and I wrote the following XAML code:
<Window x:Class="TestProject.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">
<Window.Resources>
<DataTemplate x:Key="AlphaDataTemplate">
<Label
Name="LabelInDataTemplate"
Content="Good morning!" />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentPresenter
Name="MyContentPresenter"
ContentTemplate="{StaticResource AlphaDataTemplate}" />
<Button
Name="MyButton"
Click="MyButton_OnClick"
Content="Change the content of the Label in the DataTemplate"
Width="320"
Height="30" />
</Grid>
In this XAML file I created a "DataTemplate" which corresponds to the key "AlphaDataTemplate". The DataTmplate contains just one label with the name "LabelInDataTemplate" where I have hardcoded the "Good morning!" string in the "Content" attribute of the label.
Then I use created a "ContentPresenter" with the name "MyContentPresenter" and I pass as content the "DataTemplate" I previously created (AlphaDataTemplate).
As next step, I created a "Button" with the name "MyButton" and I have set a "Click" event called "MyButton_OnClick"
So far so good...!
The question comes now and actually in C# in the code behind file "MainWindow.xaml.cs". See the code below:
using System.Windows;
namespace TestProject
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
LabelInDataTemplate.Content = "Bye!"; // <-- Tha does not work.
}
}
}
In this C# code behind file you can see the definition of the "Click" (MyButton_OnClick) event of the Button (MyButton) which appears in XAML.
What I am trying to do in this "Click" event, is to change the value of the "Content" of the "Label" (LabelInDataTemplate) which is in the DataTemplate (AlphaDataTemplate).
Unfortunately, that does not work.
I cannot actually access the "Name" (LabelInDataTemplate) of the "Label", because it is contained in the "DataTemplate" (AlphaDataTemplate)
If anyone has any idea, how could I modify from C# the value of an element which is define in a XAML DataTemplate, please give me feedback. I would really appreciate it.
Thank you in advance.
I strongly oppose your method of changing the content of label via DataTemplate, However your requirement is possible, but very subtle.
Code
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
var alphaDataTemplate = this.Resources["AlphaDataTemplate"] as DataTemplate;
var label = alphaDataTemplate.FindName("LabelInDataTemplate", MyContentPresenter) as Label;
label.Content = "It Works";
}
Please learn MVVM and use proper DataBinding for this purpose. For sake of solving this problem:
Implement INotifyPropertyChanged interface on your Window class and Define string property like below
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public string _contentMsg;
public string ContentMsg
{
get { return _contentMsg; }
set
{
_contentMsg = value;
RaisePropertyChanged("ContentMsg");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propName)
{
if(PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
In your xaml bind the ContentPresenter and update your DataTemplate label like
<ContentPresenter
Name="MyContentPresenter"
Content = "{Binding ContentMsg}"
ContentTemplate="{StaticResource AlphaDataTemplate}" />
<DataTemplate x:Key="AlphaDataTemplate">
<Label
Name="LabelInDataTemplate"
Content="{Binding}" />
Now in click handler (I would use Commands here), set ContentMsg to whatever you want
private void MyButton_OnClick(object sender, RoutedEventArgs e)
{
ContentMsg = "Bye!";
}
I implemented the control basics sample from the Kinect for Windows toolkit http://msdn.microsoft.com/en-us/library/dn188701.aspx to control the cursor with a users hand, but when I click on a sub window and then re open the main window with the hand cursor doesn't show.
My question is how do I open a new window without closing the previous window and then navigate back to the same instance of that window, not a new instance?
This is how I call a new window in my main window class:
private void trainingBtn_Click(object sender, RoutedEventArgs e)
{
var newForm = new TrainingFrm(); //create your new form.
newForm.Show(); //show the new form.
this.Close(); //only if you want to close the current form.
}
And this is how I reopen the main window, but it creates anew instance of the main window which I don't want.
private void homeBtn_Click(object sender, RoutedEventArgs e)
{
var newForm = new MainWindow(); //create your new form.
newForm.Show(); //show the new form.
this.Close(); //only if you want to close the current form.
}
What you need is composition
Here how it should look your mainWindow class
public partial class MainWindow : Window
{
private trainingWindow _trainingWindow;
public MainWindow()
{
InitializeComponent();
}
private void buttonGoTraining_Click(object sender, RoutedEventArgs e)
{
if (_trainingWindow== null)
{
_trainingWindow= new trainingWindow(this);
}
this.Visibility = Visibility.Hidden;
_trainingWindow.Show();
_trainingWindow.Visibility = Visibility.Visible;
this.Visibility = Visibility.Hidden;
}
}
and here is your training class
public partial class trainingWindow : Window
{
private MainWindow _mainWindow;
public trainingWindow(MainWindow mainWindow )
{
InitializeComponent();
_mainWindow = mainWindow;
}
private void biuttonBack_Click(object sender, RoutedEventArgs e)
{
this.Visibility = Visibility.Hidden;
_mainWindow.Visibility = Visibility.Visible;
}
}
here is the xaml
<Window x:Class="WpfApplication2.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="Button" Height="121" HorizontalAlignment="Left" Margin="112,38,0,0" Name="button1" VerticalAlignment="Top" Width="195" Click="buttonGoTraining_Click" />
</Grid>
</Window>
<Window x:Class="WpfApplication2.trainingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="trainingWindow" Height="300" Width="300">
<Grid>
<Button Content="Button" Height="36" HorizontalAlignment="Left" Margin="52,33,0,0" Name="button1" VerticalAlignment="Top" Width="97" Click="biuttonBack_Click" />
</Grid>
</Window>
Simply hide it, and not close.
If you need to show a fresh information after show, just bind a new data to its view model.
I have a user control which has a CheckBox, a Button, and a CommandBinding. If the CheckBox is checked, the Button is enabled. The MainWindow uses the UserControl. When the Button in the main window is pressed, the UserControl is removed from UI, and GC.Collect() is called, but CanExecute method still runs.
I find that if I click the button in main window twice, CanExecute will no longer run. It seems that I don't call GC.Collect() at the right time.
I want to know what is the good timing to call GC to clean the unused user control, so that CanExecute will not be called.
XAML
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<RoutedUICommand x:Key="okCommand" Text="OK"/>
</UserControl.Resources>
<UserControl.CommandBindings>
<CommandBinding Command="{StaticResource okCommand}" CanExecute="CommandBinding_CanExecute_1"/>
</UserControl.CommandBindings>
<StackPanel>
<CheckBox Name="checkBox" Content="CheckBox"/>
<Button Command="{StaticResource okCommand}" Content="{Binding Path=Text, Source={StaticResource okCommand}}"/>
</StackPanel>
</UserControl>
Code behind
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void CommandBinding_CanExecute_1(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = checkBox.IsChecked.GetValueOrDefault(false);
System.Media.SystemSounds.Beep.Play();
}
}
MainWindow
<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" Loaded="Window_Loaded_1">
<StackPanel>
<Border Name="container"/>
<Button Content="Set Null" Click="Button_Click_1"/>
</StackPanel>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
container.Child = null;
GC.Collect();
GC.WaitForPendingFinalizers();
}
private void Window_Loaded_1(object sender, RoutedEventArgs e)
{
UserControl1 uc = new UserControl1();
container.Child = uc;
}
}
Use grid as container and Container.Clear() method and forget about GC.
I find another solution. That is to call CommandBindings.Clear() in UserControl1 when it unloads.
I believe this is a neat way, since the caller of UserControl1 doesn't take care of the cleaning job of UserControl1.
I have
<Window x:Class="Repo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Repo="clr-namespace:Repo" Title="Window1" Height="300" Width="300">
<Grid>
<Button Click="SaVeEverythingInDatabase></Button>
<Repo:UserControlTasks/>
</Grid>
</Window>
public class UserControlTasks:userControl
public partial class UserControlTasks: UserControl
{
public UserControlTasks()
{
InitializeComponent();
LoadView();
}
private void LoadView()
{
this.lbTasks.ItemsSource = new TaskModelView();//collectionOfTasks
}
How to get collection from lbTasks in UserControlTasks when I click button on MainWindow?
I must add that I this collection is a part of instances of class Student which is datacontext of MainWindow.
Create TaskModelView in MainWindow class and assign it to Button control and UserControlTasks control. You will need to add a dependecy property for this to UserControlTasks.