How to change the text in my Textblock in MainWindow using iCommand? - c#

Basically I have one textblock and 2 button, I want the textblock Text to change according to the button I click. For example, if I click on the Button 1, it will display, "Button 1 is click"
if I click on button 2, it will display "Button 2 is click"
This is my ViewModel
namespace ICommandProject2.ViewModel
{
class ViewModel
{
public ICommand myCommand { get; set; }
public ViewModel()
{
myCommand = new myCommand(ExecutedMethod);
}
private void ExecutedMethod (object parameter)
{
MainWindow m = new MainWindow();
m.txtBlock.Text = "Button 1 is click";
}
}
}
This my Command Class
namespace ICommandProject2.Command
{
class myCommand : ICommand
{
Action<object> actionExecuted;
public myCommand(Action<object> ExecutedMethod)
{
actionExecuted = ExecutedMethod;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
actionExecuted(parameter);
}
}
}
This is my Mainwindow.xaml
<Window x:Class="ICommandProject2.MainWindow"
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:ICommandProject2.ViewModel"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<local:ViewModel x:Key="vm"/>
</Window.Resources>
<Grid>
<Button x:Name="btnOne" Content="Button 1" Command="{Binding myCommand, Source={StaticResource vm}}" HorizontalAlignment="Left" Margin="273,232,0,0" VerticalAlignment="Top" Width="75" FontSize="18"/>
<TextBlock x:Name="txtBlock" HorizontalAlignment="Left" Margin="273,89,0,0" TextWrapping="Wrap" Text="This is a textblock" VerticalAlignment="Top" FontSize="36"/>
<Button x:Name="btnTwo" Content="Button 2" HorizontalAlignment="Left" Margin="495,232,0,0" VerticalAlignment="Top" Width="75" FontSize="18" />
</Grid>
</Window>
When I click on the button, nothing is happening, what should I change?

use binding to set TextBlock text.
create a property fro binding in a view model and change that property in command handler:
class ViewModel : INotifyPropertyChanged
{
public ICommand myCommand { get; set; }
private string _title = "This is a textblock";
public string Title { get { return _title; } }
public ViewModel()
{
myCommand = new myCommand(ExecutedMethod);
}
private void ExecutedMethod (object parameter)
{
_title = "Button 1 was clicked";
OnPropertyChanged("Title");
}
}
I omitted that part, but you should implement INotifyPropertyChanged to notify view about changes in a view model.
use Binding in a view:
<TextBlock x:Name="txtBlock" Text="{Binding Title}" ...
(command as it is now doesn't work becuase it creates an new instance of Window (MainWindow m = new MainWindow();) instead of working with open Window)

Related

keyBinding doesn't works until a button is clicked

A usercontrol should get added every time when the shortcut is clicked. But when i close the usercontrol and try to open it again the shortcut doesn't work. The focus is somewhere else.when some button is clicked on the window and shortcut is clicked usercontrol is added.
UserControl 1:
<Window
x:class="Class1"
...>
<Window.InputBindings>
<KeyBinding Command="ButtonCLickCommand "
Modifiers="Control" Key="Q"/>
</Window.InputBindings>
<Grid x:Name="Grid">
<Button Content = "OpenUserControl" Command="ButtonCLickCommand "/>
<Button Content = "Temp"/>
</Grid>
</Window>
CodeBehind:
public ICommand ProfileCommand { get; set; }
ProfileCommand = new RelayCommand(Button_Click());
public void Button_Click()
{
_control = new Class2();
_control.CloseAction = CloseClass2;
Panel.SetZIndex(_control, 10);
_control.Width = 200;
_control.Height = 200;
Grid.Children.Add(_control);
}
public void CloseClass2(Class2 control)
{
Grid.Children.Remove(control);
}
UserControl 2:
<UserControl
x:class="Class2"
...>
<StackPanel>
<Button Content="x" Click="Button_Click" Height="30">
<Rectangle Fill="Black" Height="70"/>
</StackPanel>
</UserControl>
Code Behind:
namespace namespace1.UserControls
{
/// <summary>
/// Interaction logic for ProfileUserControl.xaml
/// </summary>
public partial class Class2 : UserControl
{
public Action<Class2> CloseAction;
public Class2()
{
InitializeComponent();
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
CloseAction(this);
}
}
}
This is outline of My code. Help me i'm new to WPF.
Thanks for every answer i get. :)
In Your KeyBinding ... you should bind to your command in View model
....
to make it easier .. it omit the view model ... here is the solution,note that i made some tweaks for simplicity:
in mainWindow.xaml :
<Window.InputBindings>
<KeyBinding Command="{Binding ButtonClickCommand,RelativeSource{RelativeSource FindAncestor,AncestorType=Window}}" Modifiers="Control" Key="Q"/>
</Window.InputBindings>
<StackPanel x:Name="MainGrid">
<Button Content = "OpenUserControl" Command="{Binding ButtonClickCommand,RelativeSource={RelativeSource FindAncestor,AncestorType=Window}}"/>
</StackPanel>
and here is the code behind:
public partial class MainWindow : Window
{
public RelayCommand ButtonClickCommand { get; set; }
public MainWindow()
{
InitializeComponent();
ButtonClickCommand= new RelayCommand(MyButtonClickExcute);
}
private void MyButtonClickExcute()
{
UserControl1 userControl1 = new UserControl1 {Width = 50, Height = 50,CloseAction = RemoveUserControlFromPanel };
Panel.SetZIndex(userControl1, 10);
MainGrid.Children.Add(userControl1);
}
public void RemoveUserControlFromPanel(UserControl1 userControl1)
{
MainGrid.Children.Remove(userControl1);
}
}
and for userControl.xaml:
<Grid>
<Border Background="Blue" CornerRadius="10" BorderThickness="15" BorderBrush="Green">
<Button VerticalAlignment="Center" HorizontalAlignment="Center" Width="125" Height="75" Content="Close" Click="ButtonBase_OnClick"></Button>
</Border>
</Grid>
finally, code behind for userControl:
public partial class UserControl1 : UserControl
{
public Action<UserControl1> CloseAction { get; set; }
public UserControl1()
{
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
CloseAction(this);
}
}

Binding User Control from second lib project not work - wpf mvvm

My task: I want to bind textbox and button.
Although I found many topics about it I cannot manage my problem.
I have project: Client with WPF application WITH DEFAULT XAML no BINDING, which takes context from MenuWindow project, which is library. Inside MenuWindow project I have User Control WPF called: MenuProgram.
<UserControl x:Class="MenuWindow.MenuProgram"
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"
xmlns:local="clr-namespace:MenuWindow"
mc:Ignorable="d"
d:DesignHeight="550" d:DesignWidth="780">
<UserControl.DataContext>
<local:MenuViewModel/>
</UserControl.DataContext>
<Grid Background="#FF6F6FA4">
<Label x:Name="lblTitle" Content="GUI Export Revit Data" HorizontalAlignment="Left" Margin="277,31,0,0" VerticalAlignment="Top" Height="50" Width="258" FontSize="24" FontWeight="Bold"/>
<Label x:Name="lblPrtdPath" Content="File prtd path" HorizontalAlignment="Left" Margin="200,176,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblXmlPath1" Content="File xml path1" HorizontalAlignment="Left" Margin="200,222,0,0" VerticalAlignment="Top"/>
<Label x:Name="lblXmlPath2" Content="File xml path2" HorizontalAlignment="Left" Margin="200,266,0,0" VerticalAlignment="Top"/>
<TextBox x:Name="tbxPrtd" HorizontalAlignment="Left" Height="23" Margin="302,176,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="268" Text="{Binding PrtdFilePath}"/>
<TextBox x:Name="tbxXml1" HorizontalAlignment="Left" Height="23" Margin="302,222,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="268" Text="{Binding XmlFilePath1}"/>
<TextBox x:Name="tbxXml2" HorizontalAlignment="Left" Height="23" Margin="302,266,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="268" Text="{Binding XmlFilePath2}"/>
<Button x:Name="SayHi" Content="Start" HorizontalAlignment="Left" Margin="302,450,0,0" VerticalAlignment="Top" Width="174" Height="84" FontSize="22" Command="{Binding SayHi}" />
<Button x:Name="btnAbout" Content="About" HorizontalAlignment="Left" Margin="705,496,0,0" VerticalAlignment="Top" Width="55" Height="38" Command="{Binding SayHi}"/>
</Grid>
so I have
<UserControl.DataContext>
<mv:MenuViewModel/>
</UserControl.DataContext>
and with textBoxs or button I want to use binding.
in codeBehind this User Control there is nothing but default initialization.
In Project Menu there are:
MenuArguments.cs with mapping:
public string PrtdFilePath { get; set; }
public string XmlFilePath1 { get; set; }
public string XmlFilePath2 { get; set; }
RelayCommand:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace MenuWindow
{
public class RelayCommand : ICommand
{
private readonly Func<Boolean> _canExecute;
private readonly Action _execute;
public RelayCommand(Action execute)
: this(execute, null)
{
}
public RelayCommand(Action execute, Func<Boolean> canExecute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
_canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add
{
if (_canExecute != null)
CommandManager.RequerySuggested += value;
}
remove
{
if (_canExecute != null)
CommandManager.RequerySuggested -= value;
}
}
public Boolean CanExecute(Object parameter)
{
return _canExecute == null ? true : _canExecute();
}
public void Execute(Object parameter)
{
_execute();
}
}
}
and MenuViewModel.cs
namespace MenuWindow
{
public class MenuViewModel : INotifyPropertyChanged
{
public string gowno;
public MenuArguments _menuArgumenty;
public string PrtdFilePath
{
get { return _menuArgumenty.PrtdFilePath; }
set
{
_menuArgumenty.PrtdFilePath = value;
OnPropertyChanged("PrtdFilePath");
}
}
public string XmlFilePath1
{
get { return _menuArgumenty.XmlFilePath1; }
set
{
_menuArgumenty.XmlFilePath1 = value;
OnPropertyChanged("XmlFilePath1");
}
}
public string XmlFilePath2
{
get { return _menuArgumenty.XmlFilePath2; }
set
{
_menuArgumenty.XmlFilePath2 = value;
OnPropertyChanged("XmlFilePath2");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public MenuViewModel()
{
_menuArgumenty = new MenuArguments();
}
public ICommand SayHi
{
get
{
return new RelayCommand(SayHiExcute, CanSayHiExcute);
}
}
private void SayHiExcute()
{
if (!MenuArgumentsExists(_menuArgumenty))
{
MessageBox.Show(string.Format("Hi {0} {1}!", _menuArgumenty.PrtdFilePath, _menuArgumenty.XmlFilePath1));
SavePerosn(_menuArgumenty);
}
else
{
MessageBox.Show(string.Format("Hey {0} {1}, you exists in our database!", _menuArgumenty.PrtdFilePath, _menuArgumenty.XmlFilePath1));
}
}
private void SavePerosn(MenuArguments _menuArgumenty)
{
//Some Database Logic
}
private bool CanSayHiExcute()
{
return !MenuArgumentsExists(_menuArgumenty);
}
private bool MenuArgumentsExists(MenuArguments _menuArgumenty)
{
//Some logic
return false;
}
}
}
When I start program debuger goes through binding properties. After window appears there is no reaction from binding. What do I do wrong? Please help me.
BR,
student Cenarius
Thanks for comments, answers to your comments:
#tabby - I want to bind textBoxes: PrtdFilePath, XmlFilePath1, XmlFilePath1 and button SayHi
#maulik kansara - You are right, I was trying some another methods and I didnt remove code. It should be only version with local.
#grek40 - My example works for one-project in solution for Window not for UserControl which is set in another project. Here is picture:
#mm8 - I expected by puting data ino textBoxes or clicking button to see breakpoint in:
public string PrtdFilePath
{
get { return _menuArgumenty.PrtdFilePath; }
set
{
_menuArgumenty.PrtdFilePath = value;
OnPropertyChanged("PrtdFilePath");
}
}
Finally, I think that code in XAML is problem. I was reading about parent-child relations with finding binding/viewmodel/path but I am confused and I dont know how to solve it. Please help me thanks You for all comments.
#grek40 here is Code in Main APP WPF, I add context from my MenuWindow.
This MainWindow WPF APP has default XAML.
public MainWindow()
{
InitializeComponent();
menuProgram = new MenuProgram();//User Control
sw = new SharedWindow();//WPF window
this.Close();
sw.Content = menuProgram.Content;// here I set context
sw.ShowDialog();
}
and XAML:
<Window x:Class="Client.MainWindow"
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:Client"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
</Grid>
</Window>
Whole code with Your change:
public partial class MainWindow : Window
{
private SharedWindow sw;
private MenuProgram menuProgram;
public MainWindow()
{
InitializeComponent();
menuProgram = new MenuProgram();
SetForContext();
}
private void SetForContext()
{
sw = new SharedWindow();
this.Close();
sw.Content = menuProgram;
sw.ShowDialog();
}
You need to set the UserControl as window Content, not the Content of UserControl:
sw.Content = menuProgram;// here I set context
/* Bad: sw.Content = menuProgram.Content; */
Your DataContext is assigned to the UserControl itself, so if you move the Content tree to a different Parent, it will no longer have its old DataContext.

MVVM Binding not working when change from event firing

I make a simple MVVM sample. I have main window with two user control pages. The main window have two event to change the view to two user control.
This is my main window XAML
<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:MVVC_Binding"
xmlns:views="clr-namespace:MVVC_Binding.Views"
xmlns:viewModel="clr-namespace:MVVC_Binding.ViewModels"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" x:Class="MVVC_Binding.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type viewModel:Page1ViewModel}">
<views:Page1 />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModel:Page2ViewModel}">
<views:Page2/>
</DataTemplate>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="Page1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="page1"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
<TextBlock Text="Page2">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding NavCommand}" CommandParameter="page2"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
<DockPanel Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Gainsboro">
<Grid x:Name="container" Background="Gainsboro" VerticalAlignment="Top">
<ContentControl Content="{Binding CurrentViewModel}"/>
</Grid>
</DockPanel>
</Grid>
</Window>
I am using the BindableBase class for my view model. This is my BindableBase class
namespace MVVC_Binding.Utilities
{
public class BindableBase : INotifyPropertyChanged
{
/// <summary>
/// Interface implementation
/// </summary>
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected virtual void SetProperty<T>(ref T member, T val, [CallerMemberName] string propertyName = null)
{
// Check for current set member and the new value
// If they are the same, do nothing
if (object.Equals(member, val)) return;
member = val;
// Invoke the property change event
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(string propName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
}
In my main view model, just simple click event to change the view binding
private BindableBase _CurrentViewModel;
public BindableBase CurrentViewModel
{
get { return _CurrentViewModel; }
set
{
SetProperty(ref _CurrentViewModel, value);
}
}
private void OnNav(string destination)
{
switch (destination)
{
case "page2":
CurrentViewModel = page2;
break;
default:
CurrentViewModel = page1;
break;
}
}
The problem is in user control Page 2, when it is display, and the event in side of it does not change the TextBlock binding value, but the text can change during the view model constructor event.
Here is my page 2 XAML
<UserControl x:Class="MVVC_Binding.Views.Page2"
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"
xmlns:local="clr-namespace:MVVC_Binding.Views"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<TextBlock Name="txtPage2" Text="{Binding Page2Text}"></TextBlock>
<TextBlock Name="btn" Text="Click Button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<i:InvokeCommandAction Command="{Binding BtnCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
</UserControl>
And here is the Page2ViewModel
namespace MVVC_Binding.ViewModels
{
public class Page2ViewModel : BindableBase
{
public MyICommand<string> BtnCommand { get; private set; }
public Page2ViewModel()
{
BtnCommand = new MyICommand<string>(OnBtnClick);
Page2Text = "Just a test";
}
private void OnBtnClick(string obj)
{
Page2Text = "Changing by button click";
}
private string _page2Text;
public string Page2Text
{
get { return _page2Text; }
set
{
_page2Text = value;
SetProperty(ref _page2Text, value);
}
}
}
}
Can you please see what I am doing wrong? Thanks so much
If I understand correctly, you're asking why the code in this function doesn't seem to have an effect on the view:
private void OnBtnClick(string obj)
{
_page2Text = "Changing by button click";
}
The problem is that you are changing the underlying _page2Text member, but in order for WPF to detect this change, you must use the Page2Text property, like this:
private void OnBtnClick(string obj)
{
Page2Text = "Changing by button click";
}
The specific part of your code that is indicating the property change to WPF is the OnPropertyChanged method in your BindableBase class.
Thanks everyone, I manage to solve it by updating the class BindableBase. The updated
namespace SilentUpdate.Utilities
{
public class BindableBase : INotifyPropertyChanged
{
/// <summary>
/// Interface implementation
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SetProperty<T>(ref T member, T val, [CallerMemberName] string propertyName = null)
{
// Check for current set member and the new value
// If they are the same, do nothing
// if (object.Equals(member, val)) return;
member = val;
// Invoke the property change event
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
}
So I comment out the check for the Object.Equals and force it to run for every value

How to call a method in c# class with parameters set in WPF user control textbox

Having a main c# class CtrlMain with method testForm it opens a WPF form (testFormCtrl)that shows a textbox and assigns a variable Xmin with the value introduced on textbox.
I want to execute method wantToExe from opened wpf user control with value introduced on textbox as a parameter
Here is what I have:
public partial class CtrlMain : UserControl
{
int mCounter;
double firstPos;
double[] currentBounds;
//ETC..
//constructor and class methods
//this opens a user control
static void testForm()
{
GenericWindow goWin;
testFormCtrl mytestFormCtrl = new testFormCtrl();
goWin = new GenericWindow(App.Current.MainWindow, mytestFormCtrl);
goWin.Title = "test";
goWin.ShowDialog();
}
//how to call this method with parameter of textbox?
public double wantToExe(double externalX){
double result;
//DO SOME COMPUTING
return result;
}
}
the testFormCtrl xaml is:
<UserControl x:Class="testFormCtrl"
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"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d">
<Grid Height="300">
<Grid>
<GroupBox Header="Location" Height="93" HorizontalAlignment="Left" Margin="4,3,0,0" Name="GBoxGridDefinition" VerticalAlignment="Top" Width="624">
<Grid>
<TextBlock Height="20" HorizontalAlignment="Left" Margin="20,13,0,0" Name="TblockXmin" Text="Xmin:" VerticalAlignment="Top" Width="36" />
<TextBox Name="TextBoxXmin" Height="20" Width="89" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="59,9,0,0" Text="{Binding Path=Xmin, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True,NotifyOnValidationError=True}" >
</TextBox>
<telerik:RadButton Content="Execute X" IsEnabled="True" Height="22" HorizontalAlignment="Left" Margin="484,9,0,0" Name="ButtonExecuteX" VerticalAlignment="Top" Width="102" telerik:StyleManager.Theme="Vista" />
</Grid>
</GroupBox>
</Grid>
</Grid>
</UserControl>
and c# code is
public partial class testFormCtrl : UserControl
{
double gnXmin;
public event PropertyChangedEventHandler PropertyChanged;
public double Xmin
{
get { return gnXmin; }
set
{
gnXmin = value;
OnPropertyChanged("Xmin");
}
}
void OnPropertyChanged(string lcProperty)
{
if (this.PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(lcProperty));
}
}
public testFormCtrl ()
{
InitializeComponent();
}
private void ButtonExecuteX_Click(object sender, RoutedEventArgs e)
{
//how to call CtrlMain.wantToExe(Xmin) ???
}
}
}
How can I call that method from other class, I can not make it static....
Just create a new constructor for your testFormCtrl class that accepts CtrlMain as a parameter:
private CtrlMain _caller;
public testFormCtrl(CtrlMain caller)
: this()
{
_caller = caller;
}
Then you can just invoke its methods:
private void ButtonExecuteX_Click(object sender, RoutedEventArgs e)
{
if(_caller != null) caller.wantToExe(Xmin);
}
Remember to pass the instance of CtrlMain in your testForm method:
static void testForm()
{
GenericWindow goWin;
testFormCtrl mytestFormCtrl = new testFormCtrl(this); //use the new constructor
goWin = new GenericWindow(App.Current.MainWindow, mytestFormCtrl);
goWin.Title = "test";
goWin.ShowDialog();
}

Data Binding between two TextBoxes in different windows

I have created a program that changes the name in a TextBox when check or unckeck a Checkbox. I want to replicate this Textbox in a different window. I thought with Data Mining in the xaml would be possible, but the name only appears in one window. Second window window does´t recieve the data. I show you the code of the two windows.
Can you help me? Thankss
Window 1.cs---
namespace WpfApplication1
{
public partial class Window1 : Window
{
Texto prueba = new Texto("Carlos");
public static string s;
public Window1()
{
InitializeComponent( );
// Fill initial person fields
this.textBox1.Text = prueba.Name;
}
private void checkBox1_Checked(object sender, RoutedEventArgs e)
{
prueba.Name="Carlos";
textBox1.DataContext = prueba;
textBox1.Text = prueba.Name;
}
private void checkBox1_UnChecked(object sender, RoutedEventArgs e)
{
prueba.Name = "Luis";
textBox1.DataContext = prueba;
textBox1.Text = prueba.Name;
}
}
public class Texto
{
string name;
public string Name
{
get { return this.name; }
set { this.name = value; }
}
public Texto( ) {}
public Texto(string name)
{
this.name = name;
}
}
}
window1 xaml-------
<Grid>
<CheckBox Content="CheckBox" Height="16" HorizontalAlignment="Left" Margin="62,118,0,0" Name="checkBox1" VerticalAlignment="Top" Checked="checkBox1_Checked" Unchecked="checkBox1_UnChecked" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="44,140,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
</Grid>
window2 cs-----
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Window1 nueva = new Window1();
nueva.Show();
}
}
}
window2 xaml--------
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="82,121,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<TextBox DataContext="prueba" Text="{Binding Path=Name}" Height="23" HorizontalAlignment="Left" Margin="57,84,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
</Grid>
You will have to pass a reference to either the first window or the object that you're updating the text property on to the second window, it's DataContext property will do for that, you can then bind the second windows controls to it.
In this demo application I've created a MainWindow and a second window (Window1), the application starts in Main window like this.
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public string TestString
{
get { return (string)GetValue(TestStringProperty); }
set { SetValue(TestStringProperty, value); }
}
public static readonly DependencyProperty TestStringProperty = DependencyProperty.Register("TestString", typeof(string), typeof(MainWindow), new UIPropertyMetadata(null));
public MainWindow()
{
InitializeComponent();
// setup the test string.
TestString = "this is a test.";
// Create the second window and pass this window as it's data context.
Window1 newWindow = new Window1()
{
DataContext = this
};
newWindow.Show();
}
}
MainWindow.xaml - Take note of the DataContext line in the Window declaration.
<Window x:Class="WpfApplication5.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"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Grid>
<TextBox Text="{Binding TestString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Margin="91,84,185,189" />
</Grid>
</Window>
Now for Window1 the code behind is just an empty default window class so I won't post it but the xaml is.
Window1.xaml
<Window x:Class="WpfApplication5.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<TextBlock Text="{Binding TestString, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</Window>
Don't set the DataContext explicitly, or only via another Binding. Your
<TextBox DataContext="prueba"
does nothing helpful. DataContext will be inherited as long as it is not overwritten. Don't set it explicitly. It should be enought to set it once on both windows.
Create your data object in your MainWindow
Texto prueba = new Texto("Carlos");
Window1 nueva = new Window1();
nueva.DataContext = prueba;
nueva.Show();
and remove all the other DataContext assignments.
A couple of things wrong here, but I can probably give you a quick solution to fix your problem. First off your DataContext on window 2 isn't working properly, you can set it exclusively in your code right before you show window1...
private void button1_Click(object sender, RoutedEventArgs e)
{
Window1 nueva = new Window1();
this.DataContext = nueva.prueba;
nueva.Show();
}
Next you have to fire INotifyPropertyChanged in your Texto class...
public class Texto : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string name;
public string Name
{
get { return this.name; }
set
{
this.name = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
public Texto( ) {}
public Texto(string name)
{
this.name = name;
}
}
If both textboxes share a common datacontext it will "just work" without any code required...

Categories