Unable to add a new row to the observablecollection listbox? - c#

In my project I have the following pages:
Mainwindow.xaml
Window1.xaml
User.cs
App.xaml
I declared the Name and Age property in User.cs and on MainWindow.xaml I made a ObservableCollection for a ListBox. MainWindow has a Button Add. When we click on the Add button. Then the Window1.xaml form is displayed. Which has two TextBoxes of name and age and a button (ADD Name). Now I want when we click on the Add Name button then the details in the both text boxes are attached to the ObservableCollection that is defined on the Mainwindow.xaml.cs.
Please suggest me want can I do:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void OnInit(object sender, RoutedEventArgs e)
{
string textA=textBox1.Text;
int textB=Convert.ToInt32(textBox2.Text);
this.DataContext = new User(textA, textB);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
User user = (User)(this.DataContext);
new MainWindow().observableCollection.Add(user);
this.Close();
}
}
now I ran this code I am unable to get the values in the user object.

The problem is you are not accessing the MainWindow CbservableCollection, you are creating a new MainWindow.
If this Window1 is a dialog you have a few options
Pass the MainWindow into Window1 as its owner
Use the Window1 as a dialog and fetch the changes when it closes
personally I think the 2nd option is the best, but it depends how you are calling Window1
Example2:
MainWindow Class
public partial class MainWindow : Window
{
private ObservableCollection<User> _myList = new ObservableCollection<User>();
public MainWindow()
{
InitializeComponent();
}
public ObservableCollection<User> MyCollection
{
get { return _myList; }
set { _myList = value; }
}
private void button1_Click_1(object sender, RoutedEventArgs e)
{
var dialog = new Window1();
if (dialog.ShowDialog() == true)
{
MyCollection.Add(dialog.NewUser);
}
}
}
MainWindow xaml
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="233" Width="405" Name="UI">
<Grid DataContext="{Binding ElementName=UI}" >
<ListBox ItemsSource="{Binding MyCollection}" DisplayMemberPath="TextA" Margin="0,0,0,47" />
<Button Content="Add" Height="23" HorizontalAlignment="Left" Margin="0,0,0,12" Name="button1" VerticalAlignment="Bottom" Width="75" Click="button1_Click_1" />
</Grid>
</Window>
Window1 xaml
<Window x:Class="WpfApplication8.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="119" Width="300" Name="UI">
<StackPanel DataContext="{Binding ElementName=UI}">
<TextBox Text="{Binding NewUser.TextA}" />
<TextBox Text="{Binding NewUser.TextB}" />
<Button Click="button1_Click" HorizontalAlignment="Right" Width="90" Height="30" Content="Add" />
</StackPanel>
</Window>
Window1 code
public partial class Window1 : Window, INotifyPropertyChanged
{
private User _newUser = new User();
public Window1()
{
InitializeComponent();
}
public User NewUser
{
get { return _newUser; }
set { _newUser = value; NotifyPropertyChanged("NewUser"); }
}
private void button1_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
User Class
public class User : INotifyPropertyChanged
{
private string _textA;
private string _textB;
public string TextA
{
get { return _textA; }
set { _textA = value; NotifyPropertyChanged("TextA"); }
}
public string TextB
{
get { return _textB; }
set { _textB = value; NotifyPropertyChanged("TextB"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}

Related

Raise a event on the User control from the Main Window in WPF

There is a textbox in my mainwindow.xaml, when I enter the textbox, I expect the label in my usercontrol, known as View1.xaml will be update accordingly. However I realise the event is not raise at all in the user control when I type the textbox, can you tell me which part is wrong?
The event is able to raise in TextBox_TextChanged_1
my MainWindow.XAML
<Window xmlns:my="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:testapplication" x:Class="testapplication.MainWindow"
Title="MainWindow" Height="964" Width="790">
<Grid >
<Button x:Name="OpenView1" Content="Open Window 1" HorizontalAlignment="Left" Margin="33,70,0,0" VerticalAlignment="Top" Width="111" RenderTransformOrigin="0.279,1.409" Click="OpenView1_Click"/>
<Button x:Name="OpenView2" Content="Open Window 2" HorizontalAlignment="Left" Margin="33,169,0,0" VerticalAlignment="Top" Width="111" Click="OpenView2_Click"/>
<Button x:Name="OpenView3" Content="Open Window 3" HorizontalAlignment="Left" Margin="33,259,0,0" VerticalAlignment="Top" Width="111" Click="OpenView3_Click"/>
<local:View1 x:Name="ViewOne" HorizontalAlignment="Left" Margin="33,332,0,0" VerticalAlignment="Top" Height="226" Width="204" Visibility="Hidden"/>
<local:View2 x:Name="ViewTwo" HorizontalAlignment="Left" Margin="284,332,0,0" VerticalAlignment="Top" Height="226" Width="208" Visibility="Hidden"/>
<local:View3 x:Name="ViewThree" HorizontalAlignment="Left" Margin="534,332,0,0" VerticalAlignment="Top" Height="226" Width="196" Visibility="Hidden"/>
<TextBox HorizontalAlignment="Left" Height="42" Margin="326,70,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="182" FontSize="22" TextChanged="TextBox_TextChanged_1"/>
</Grid>
</Window>
my MainWindow.cs
namespace testapplication
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
//InitializeComponent();
}
//event handler
public event EventHandler<EventArgs> changedText;
private void OpenView1_Click(object sender, RoutedEventArgs e)
{
ViewOne.Visibility = Visibility.Visible;
}
private void OpenView2_Click(object sender, RoutedEventArgs e)
{
ViewTwo.Visibility = Visibility.Visible;
}
private void OpenView3_Click(object sender, RoutedEventArgs e)
{
ViewThree.Visibility = Visibility.Visible;
}
private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
{
if (changedText != null)
{
changedText(this, e);
}
}
}
}
This is my UserControl, known as View1.xaml, it is included in my MainWindow.Xaml
namespace testapplication
{
/// <summary>
/// Interaction logic for View1.xaml
/// </summary>
public partial class View1 : UserControl
{
private MainWindow newWindow = new MainWindow();
public View1()
{
InitializeComponent();
newWindow.changedText += newWindow_ChangeText;
}
void newWindow_ChangeText(object sender, EventArgs e)
{
ViewOnelabel.Content = "Happy";
}
}
}
The problem is my ViewOnelabel.Content = "Happy" did not execute at all, it remain unchanged
There are a few things I would like to point out.
The equivalent of a winforms label in wpf is a TextBlock. A wpf label is actually a type of contentcontrol. Hence the content property.
In wpf there are routed events. These "bubble" up ( and tunnel down ) the visual tree. That means you can handle an event in the window from a control in a usercontrol inside it.
But mainly.
I encourage you to look into the MVVM pattern.
I've put together some code which illustrates these points.
I'd recommend just using binding and mvvm though.
My MainWindow markup:
Title="MainWindow" Height="350" Width="525"
TextBoxBase.TextChanged="Window_TextChanged"
>
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<StackPanel>
<Label Name="OutputLabel"/>
<TextBlock Text="{Binding OutputString}"/>
<local:UserControl1/>
</StackPanel>
</Grid>
Notice that it handles a textchanged event and because that's routing it will get the event from UserControl1 inside it.
Code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_TextChanged(object sender, TextChangedEventArgs e)
{
OutputLabel.Content = $"Happy {((TextBox)e.OriginalSource).Text}";
}
}
You don't do anything with the text from your textbox in your handler but I have some code there proves you could get at that from mainwindow if you wanted.
My viewmodel:
public class MainWindowViewModel : INotifyPropertyChanged
{
private string inputString;
public string InputString
{
get { return inputString; }
set
{
inputString = value;
OutputString = $"{inputString.Length} characters entered";
RaisePropertyChanged();
}
}
private string outputString;
public string OutputString
{
get { return outputString; }
set
{
outputString = value;
RaisePropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Usercontrol1 just has a textbox:
<Grid>
<TextBox Text="{Binding InputString, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
As you type in that textbox, the text is transferred to the bound property in my viewmodel. That hits the code in my setter. This in turn sets OutputString which is bound to my textblock.
Text changes in both my label and textblock as I type.
Here's a link to my sample on onedrive
https://1drv.ms/u/s!AmPvL3r385QhgpgOPNKPs-veFJ2O3g
The main problem here is that your View1 class is subscribing to an event on a new MainWindow instance, not the MainWindow instance created by your application on start.
Since your MainWindow class has a reference to your View1 class (a named member "ViewOne") you should just change it from the MainWindow class.
private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
{
ViewOne.ViewOneLabel.Content = "Happy";
}
Get rid of the chenagedText event handler and all the code in the View1.xaml.cs... you don't need it.
Note: I am hoping that you are just playing around and learning here... there is no way I would condone building a WPF application in this way.
You could only use the event of the MainPage. I recomment you to add a Property to the UserControl. In my case I call it Text.
public string Text
{
set { ViewOneLabel.Content = value; }
}
In the MainWindow use the Property within the TextChanged Event.
private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
{
OpenView1.Text = TextBox.Text;
}
You are creating a new instance of MainWindow in your UserControl. What you want to do is to hook up an event handler to the instance that you actually see on the screen. You can get a reference to this one using the Window.GetWindow method:
public partial class View1 : UserControl
{
public View1()
{
InitializeComponent();
Loaded += (s, e) =>
{
Window mainWindow = Window.GetWindow(this) as MainWindow;
if(mainWindow != null)
mainWindow.changedText += newWindow_ChangeText;
};
}
void newWindow_ChangeText(object sender, EventArgs e)
{
ViewOnelabel.Content = "Happy";
}
}

How do I access XAML bound class properties in code? (C#, WPF form)

In the example below, I am using XAML to set the DataContext to a class name, not an object name (as far as I can tell). The binding works - the txtEcho textbox shows what is entered in the txtName textbox when the latter loses focus. I want to be able to access the properties of this class in code-behind so I need an object reference. I could create a Person object and set the DataContext to that but the pattern in the books I am consulting does not do that - the class name is used and an object is not explicitly created in the examples in these textbooks.
<Window x:Class="WpfApplication5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication5"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:Person x:Key="personData" />
</Window.Resources>
<Grid>
<Grid.DataContext>
<Binding Source="{StaticResource personData}" />
</Grid.DataContext>
<TextBlock HorizontalAlignment="Left" Margin="27,41,0,0" TextWrapping="Wrap" Text="Name" VerticalAlignment="Top" Height="23"/>
<TextBox x:Name="txtName" Text="{Binding Name}" HorizontalAlignment="Left" Height="23" Margin="78,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<TextBox x:Name="txtEcho" Text="{Binding Name}" HorizontalAlignment="Left" Height="23" Margin="262,42,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
</Grid>
</Window>
The code is
namespace WpfApplication5
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//txtFreedom.Text = <what exactly?>.Name; // no object reference!
}
}
class Person : INotifyPropertyChanged
{
string name;
public string Name
{
get { return this.name; }
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You could access the Person instance that you create in your XAML like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
Person person = this.Resources["personData"] as Person;
txtFreedom.Text = person.Name;
}
I found a way, with mm8's help. The code is now
namespace WpfApplication5
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public static Person oPerson;
public MainWindow()
{
InitializeComponent();
oPerson = this.Resources["personData"] as Person;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
txtFreedom.Text = oPerson.Name;
}
}
public class Person : INotifyPropertyChanged
{
string name;
public string Name
{
get { return this.name; }
set
{
this.name = value;
OnPropertyChanged("Name");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
The differences are, Declare a public static variable to hold a Person object.
public static Person oPerson;
In the MainWindow() method set it to the behind-the-scenes Person instance.
oPerson = this.Resources["personData"] as Person;
I had to make the class public to stop a compiler accessibility objection.
public class Person : INotifyPropertyChanged
Now I can reference the properties of the instance.
private void Button_Click(object sender, RoutedEventArgs e)
{
txtFreedom.Text = oPerson.Name;
}

Data binding in WPF using code behind

I have a scenario where I would want to bind a string property to a text box on the UI when the string property changes.I would want to change the property in the code behind.Please find my work below :
XAML :
<Window x:Class="databinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:test="clr-namespace:databinding"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Text="{Binding mobile1}" Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
<TextBox Text="{Binding mobile2}" Height="23" HorizontalAlignment="Left" Margin="10,43,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" />
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="10,76,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
Please find the MainWindow.xaml.cs below :
namespace databinding
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void button1_Click(object sender, RoutedEventArgs e)
{
talk ta = new talk();
ta.test();
}
}
}
Please find the class where I have defined my properties :
mobile.cs :
namespace databinding
{
public class mobile:INotifyPropertyChanged
{
string mobile1model;
string mobile2model;
public string mobile1 { get { return mobile1model; } set { mobile1model = value; OnPropertyChanged(new PropertyChangedEventArgs("mobile1")); } }
public string mobile2 { get { return mobile2model; } set { mobile2model = value; OnPropertyChanged(new PropertyChangedEventArgs("mobile2")); } }
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
{
PropertyChanged(this, e);
}
}
}
}
now I have a test class where I change the property value :
test.cs :
namespace databinding
{
public class talk:MainWindow
{
public void test()
{
mobile mb = new mobile();
mb.mobile1 = "This is mobile 1";
mb.mobile2 = "This is mobile 2";
}
}
}
The problem statement here is that when I click the button1 the properties get updated but the textboxes on the UI does not get updated,also I am looking if the textboxes are updates as soon as the property changes or is it going to wait till the second property changes to get updated? Appreciate your support for this query.
Thanks in advance.
Create one instance of mobile class, set it as Window.DataContext and call test() on that instance
public partial class MainWindow : Window
{
private readonly mobile _mb = new mobile();
public MainWindow()
{
InitializeComponent();
DataContext = _mb;
}
public void test()
{
_mb.mobile1 = "This is mobile 1";
_mb.mobile2 = "This is mobile 2";
}
void button1_Click(object sender, RoutedEventArgs e)
{
this.test();
}
}

Trying to understand how i can bind a WPF DP in a different class

I am trying WPF to develop a tiny scoreboard.
In this project i have 3 XAML files.
ControlDisplay.xaml : Here is where i set the points for team 1 and team 2 in the scoreboard. Right now i only have 1 textbox for the scoreboard title.
Layout1.xaml : First layout, contains only a title for now.
Layout2.xaml : Second layout, same as above, only contains a title.
My idea is as following. I update one singleton class that has one property Title. Both Layout1 and Layout2's label for the title will bind to this singleton class property Title.
I created the basic structure for it.
ControlDisplay.xaml:
public partial class ControlDisplay : Window
{
private IScoreboardData _scoreboardData;
private Layout1 _layout1;
private Layout2 _layout2;
public ControlDisplay()
{
InitializeComponent();
_scoreboardData = SimpleInjectorContainer.Container.GetInstance<IScoreboardData>();
}
private void ShowLayout1(object sender, RoutedEventArgs e)
{
_scoreboardData.Title = "Test";
_layout1 = new Layout1();
_layout1.Show();
}
private void ShowLayout2(object sender, RoutedEventArgs e)
{
_scoreboardData.Title = "Test";
_layout2 = new Layout2();
_layout2.Show();
}
}
Layout1.xaml.cs (layout2 is a copy of layout1 codewise, just a different class name)
public partial class Layout1 : Window
{
private IScoreboardData _scoreboardData;
public Layout1()
{
_scoreboardData = SimpleInjectorContainer.Container.GetInstance<IScoreboardData>();
InitializeComponent();
}
}
Layout1.xaml
<Window x:Class="SmallScoreboard.Layout1" .... x:Name="LayoutOne">
<StackPanel>
<Label DataContext="{Binding ElementName=LayoutOne}" Content="{Binding _scoreboardData.Title}" />
</StackPanel>
</Window>
ScoreboardData.cs
public ScoreboardData : IScoreboardData
{
public string Title { get; set; }
}
This obviously does not work since i don't register a dependency property anywhere? How can i register a dependency property inside the ScoreboardData class? or is there a better way to solve this?
I want to be able to add more layouts in the future and i hope that i don't have to add the base binding logic to each and everyone of those layout(x).xaml.cs files.
Update
This is my Layout1.xaml file right now:
<Window x:Class="Simple_Scoreboard.Layout1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Layout" Height="500" Width="800"
ScrollViewer.VerticalScrollBarVisibility="Hidden" ScrollViewer.HorizontalScrollBarVisibility="Hidden"
WindowStyle="None"
AllowsTransparency="True"
ResizeMode="CanResizeWithGrip"
x:Name="LayoutOne" MouseLeftButtonDown="DWindow_MouseLeftButtonDown">
<StackPanel>
<Label Content="{Binding Path=Title, Mode=OneTime}" FontSize="30" HorizontalAlignment="Center" HorizontalContentAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" Margin="0,10,0,0" FontWeight="Bold"></Label>
<Button Content="Button" Click="Button_Click_1"/>
</StackPanel>
</Window>
and the Layout1.xaml.cs
public partial class Layout1 : Window
{
public IScoreboardData _scoreboardData;
public Layout1()
{
InitializeComponent();
_scoreboardData = ScoreboardContainer.Container.GetInstance<IScoreboardData>();
DataContext = _scoreboardData;
}
private void DWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
_scoreboardData.Title = "Click change title";
}
}
and finally the ScoreboardData class:
class ScoreboardData : IScoreboardData, INotifyPropertyChanged
{
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Title"));
}
}
#region INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
I think your problem is in binding to a private field _scoreboardData;
you should make it a public property. But much better solution would be to bind to a window DataContext.
in the window constructor
public Layout1()
{
_scoreboardData = SimpleInjectorContainer.Container.GetInstance<IScoreboardData>();
InitializeComponent();
DataContext = _scoreboardData;
}
In the XAML
<Window x:Class="SmallScoreboard.Layout1" .... x:Name="LayoutOne">
<StackPanel>
<Label Text="{Binding Title}" />
</StackPanel>
</Window>
This way you have your scoreBoardData as Window DataContext and all bindings without explicitly specified source will bind to that object.
UPDATE:
ScoreboardData should implement INotifyPropertyChanged..
public class ScoreboardData :IScoreboardData, System.ComponentModel.INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
if(PropertyChanged!=null)
PropertyChanged(this,new PropertyChangedEventArgs("Title"));
}
}
}

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