WPF Passing Data Between Clone Windows - c#

I have a MainWindow and there is a button in MainWindow to open ClientWindow.
private void btnMakeClient_Click(object sender, RoutedEventArgs e)
{
ClientWindow window = new ClientWindow();
window.Show();
}
Forexample; if i 3 times click, then it opens 3 ClientWindow (chatWindow). How can i pass data(text) between these clone windows? I mean i write "hi how are you?" in a ClientWindow (chatWindow) and it appears in another windows too.
I thought that if i pass data(text) from ClientWindow with a MainWindow constructor and get it back with ClientWindow constructor would solve my problem but it did not. Here is my code
MainWindow:
public partial class MainWindow : Window
{
public string TextContent { get; set; }
public MainWindow()
{
InitializeComponent();
}
public MainWindow(string txtContext)
{
InitializeComponent();
TextContent = txtContext;
ClientWindow window = new ClientWindow(TextContent);
}
private void btnMakeClient_Click(object sender, RoutedEventArgs e)
{
ClientWindow window = new ClientWindow();
window.Show();
}
}
ClientWindow:
public partial class ClientWindow : Window
{
public string Chatcontent { get; set; }
public ClientWindow()
{
InitializeComponent();
}
public ClientWindow(string chatContent)
{
InitializeComponent();
Chatcontent = chatContent;
if (chatContent != string.Empty)
{
this.txtContent.Text += Environment.NewLine + Chatcontent;
txtChat.Clear();
}
}
private void btnSend_Click(object sender, RoutedEventArgs e)
{
MainWindow window = new MainWindow(txtChat.Text);
}
}

This is where MVVM shines. Create a ViewModel object that contain a String property and a Command to add text to this property and then in client windows just call this command with the text to add as parameter.
Note that I use DelegateCommand as described here but you can also use RelayCommand.
ViewModel
public class YourViewModel : INotifyPropertyChanged {
private String _textContent;
public String TextContent {
get {return _textContent;}
set {
_textContent = value;
OnPropertyChanged("TextContent");
}
}
private DelegateCommand _cmdAddTextToChat;
/// <summary>
/// Add text to TextContent
/// </summary>
public DelegateCommand CmdAddTextToChat {
get { return _cmdAddTextToChat ?? (_cmdAddTextToChat = new DelegateCommand(AddTextToChat)); }
}
private void AddTextToChat(Object parameter) {
TextContent += (String)parameter;
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName) {
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public partial class MainWindow : Window
{
private YourViewModel _vm = new YourViewModel ();
public MainWindow()
{
InitializeComponent();
}
public MainWindow(string txtContext)
{
InitializeComponent();
_vm.TextContent = txtContext;
ClientWindow window = new ClientWindow() {DataContext = _vm};
}
private void btnMakeClient_Click(object sender, RoutedEventArgs e)
{
ClientWindow window = new ClientWindow() {DataContext = _vm};
window.Show();
}
}
public partial class ClientWindow : Window
public ClientWindow()
{
InitializeComponent();
}
}
ClientWindow xaml:
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<TextBox x:Name="InputTextBox"/>
<Button Command="{Binding CmdAddTextToChat, Mode=OneWay}" CommandParameter="{Binding ElementName=InputTextBox, Path=Text}">
</StackPanel>
<TextBlock DockPanel.Dock="Top" Text="{Binding TextContent, Mode=OneWay}"/>
</DockPanel>
Edit: without DataContext
If you don't want to set the DataContext you can use another DP (Tag could be used, you can also create a new one):
#region ViewModelObject
public YourViewModel ViewModelObject
{
get { return (YourViewModel)GetValue(ViewModelObjectProperty); }
set { SetValue(ViewModelObjectProperty, value); }
}
private readonly static FrameworkPropertyMetadata ViewModelObjectMetadata = new FrameworkPropertyMetadata {
};
public static readonly DependencyProperty ViewModelObjectProperty =
DependencyProperty.Register("ViewModelObject", typeof(YourViewModel), typeof(ClientWindow), ViewModelObjectMetadata);
#endregion
And in your click event
private void btnMakeClient_Click(object sender, RoutedEventArgs e)
{
ClientWindow window = new ClientWindow() {YourViewModelObject = _vm};
window.Show();
}

You can create a class for message with Text property and implement INotifyPropertyChanged in this class. Then store an instance of this class in MainWindow and pass it to constructor of your ClientWindow. Set it to DataContext and create a binding to Text property (in TextBox, for example). When you update Text property the other windows will see this changes.

Related

Subdialog is shown one more time on each activation of parent Dialog

I developed an app, where the user sects on order from a list. If the order is selected, the EditOrderWindow shows. From this window, the user can add items to the Order by. This is done in a sub dialog AddItemWindow. Works fine for the first order.
However, if a second order is edited, the AddItemWindow shows again after its been closed. For the third order edited it shows three times aso.
I couldn't figure out why this happens, and how to prevent it.
ViewModel
public class ViewModel
{
public ICommand EditOrderCommand { get; set; }
public ICommand AddItemCommand { get; set; }
public event EventHandler<int> EditOrder;
public event EventHandler<int> AddItem;
public event EventHandler<int> ItemAdded;
public ViewModel()
{
//Is fired when an item in the datagrid in Control OrderList is doubleclicked
EditOrderCommand = new ICommand();
EditOrderCommand.Executed += EditOrderCommand_Executed();
//Is fired when the users click on add in EditOrderWindow
AddItemCommand = new ICommand();
AddItemCommand.Executed += AddItemCommand_Executed();
}
private void EditOrderCommand_Executed(object sender, EventArgs e)
{
if (SelectedOrder != null)
{
EditOrder(this, SelectedOrder.Id);
}
}
private void AddItemCommand_Executed(object sender, EventArgs e)
{
AddItem(this, new EventArgs());
}
}
Control: OrderList
public partial class OrderList : UserControl
{
ViewModel vm;
public OrderList()
{
InitializeComponent();
//DataContext is set in xmal
vm = (ViewModel)this.DataContext;
vm.EditOrder += Vm_EditOrder;
}
private void Vm_EditOrder(object sender, int e)
{
EditOrderWindow s = new EditOrderWindow(vm);
s.ShowDialog();
s = null;
}
Window: EditOrderWindow
public partial class EditOrderWindow : Window
{
ViewModel vm;
AddItemWindow aiw;
public EditOrderWindow(ViewModel _vm)
{
InitializeComponent();
vm = _vm;
this.DataContext = vm;
vm.AddItem -= Vm_AddItem;
vm.AddItem += Vm_AddItem;
}
private void Vm_AddItem(object sender, EventArgs e)
{
if (aiw == null)
{
aiw = new AddItemWindow(vm);
}
aiw.ShowDialog();
aiw = null;
}
}
Window: AddItemWindow
public partial class AddItemWindow : Window
{
public AddItemWindow(ViewModel _vm)
{
InitializeComponent();
this.DataContext = _vm;
_vm.ItemAdded -= _vm_ItemAdded;
_vm.ItemAdded += _vm_ItemAdded;
}
private void _vm_ItemAdded(object sender, EventArgs e)
{
this.Close();
}
}

modify a listview content from a another window

i'm coding in c#/wpf (i'm a beginner), i have 2 windows:
window1 contains a listview , window2 contains textboxes in which i retrieve their values to do some treatement to obtain in the end a list(collection that i created) in window2 and the problem is that :
i want to fill my listview (window1) from window2 with the iformations obtained from the collection (window2); but i can't
code window1
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Ajouter_Click(object sender, RoutedEventArgs e)
{
Window1 a = new Window1();
a.List_inf = new List<Listview_content>();
viewMed.ItemsSource = a.List_inf;
a.Show();
}
code window2
public partial class Window1 : Window
{
public List<Listview_content> list_inf;
public List<Listview_content> List_inf
{
get { return list_inf; }
set { list_inf = value; }
}
public Window1()
{
InitializeComponent();
}
private void valider_Click(object sender, RoutedEventArgs e)
{
Listview_content med_inf = new Listview_content();
med_inf.marque = "marque";
med_inf.restitue = true;
med_inf.quant = 40;
med_inf.prix = 14;
list_inf.Add(med_inf);
}
An easy solution :)
In Window2 create a list
public class window2
{
public List<string> ItemList = new List<string>;
public void btn_Add()
{
ItemList.Add("StringHere");
}
}
In Window1
public class window1
{
Window2 win2 = new Window2;
public void btn_Click()
{
win2.showDialog();
foreach (var item in win2.ItemList)
{
combobox1.Items.Add(item.tostring);
}
}
}

Interaction between two user controls in windows form application

I created two user controls which called UserControl1 and UserControl2, UserControl1 contains TextBox1 and UserControl2 contains Button1. In the UserControl2, I want to get TextBox1.Text from UserControl1 when click Button1.
This is revelant code:
In UserControl1:
public partial class UserControlA: UserControl
{
public UserControlA()
{
InitializeComponent();
}
public string TexBoxText
{
get
{
return this.textBox1.Text;
}
}
}
In UserControl2:
public partial class UserControlB: UserControl
{
public UserControlB()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//here is to get textbox1.text
}
}
What should I do?
One option is passing UserControlA instance to UserControlB's constructor.
public partial class UserControlB: UserControl
{
UserControlA userControlA;
public UserControlB(UserControlA ucA)
{
userControlA = ucA;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string myString = userControlA.TexBoxText;
}
}
In UserControl1:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public TextBox TextBox
{
get
{
return textBox1;
}
}
}
In UserControl2:
public partial class UserControl2 : UserControl
{
private TextBox txt = null;
public UserControl2()
{
InitializeComponent();
}
public TextBox TextBox
{
set
{
txt = value;
}
}
private void button1_Click(object sender, EventArgs e)
{
if (txt != null)
MessageBox.Show(txt.Text);
}
}
In above controls' container:
uc2.TextBox = uc1.TextBox;

Event Handler Null

In the MainWindow constructor, I am registering an event handler:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
pageViewDocText = new PageViewDocText();
framePageDocFieldDetail.Content = pageViewDocText;
pageViewDocText.NewPageIRPRO += new GabeLib.SearchCls.DocEventHandler(ViewIPRO);
}
protected void ViewIPRO(string IRPOlink) // ...
}
public partial class PageViewDocText : Page, INotifyPropertyChanged
{
public event GabeLib.SearchCls.DocEventHandler NewPageIRPRO;
private void btn_PageBreakNext(object sender, RoutedEventArgs e)
{
// this fires but NewPageIRPRO is null
if (NewPageIRPRO != null)
{
NewPageIRPRO("dummylink");
}
}
}
But in PageViewDocText, NewPageIRPRO is null
What am I doing wrong?
From PageViewDocText, I want to call MainWindow.ViewIPRO.
This event handler fires and is registered the line below pageViewDocText.NewPageIRPRO +=
App.StaticGabeLib.Search.NewDocIRPRO += new GabeLib.SearchCls.DocEventHandler(ViewIPRO);
Looks like you are calling an event from another class (not listed) and there is a missing delegate.
Try this code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
pageViewDocText = new PageViewDocText();
framePageDocFieldDetail.Content = pageViewDocText;
pageViewDocText.PageBreakNext += new PageBreakNext(ViewIPRO);
}
protected void ViewIPRO(string IRPOlink) // ...
}
public partial class PageViewDocText : Page, INotifyPropertyChanged
{
public delegate void PageBreakNext(string IRPOlink);
public event PageBreakNext PageBreak;
private void btn_PageBreakNext(object sender, RoutedEventArgs e)
{
// this fires but NewPageIRPRO is null
if (PageBreak != null)
{
PageBreak("dummylink");
}
}
}

No data is set when wpf window is loaded?

I have a issue with passing information from one wpf window to another. For some reason when main window is loaded nothing is set in the label, I need to be able to keep the data in a string to use for anything (label not important but shows what I mean)?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public string MyData { get; set; }
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
label1.Content = MyData;
}
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
string mytext = "blabla";
MainWindow fromloginwindow = new MainWindow();
fromloginwindow.Mydata = mytext;
}
Or am I doing this the wrong way round?
EDIT:
Please do not go on a tangent about the label its unimportant I need to be able to get and set a string for use anywhere in the MainWindow. Also the string "mytext" is also irrelevant as obviously I will not be setting the string this way.
It sounds like you are running into an event lifecycle issue; the calls to the Loaded event happen pretty quickly and thus, the chance to set the text has passed. Instead, what you should do is either:
1) Bind the Property to the Label in the XAML
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
protected string _myData = string.Empty;
public string MyData
{
get { return _myData; }
set { _myData = value; NotifyPropertyChanged("MyData"); }
}
protected void NotifyPropertyChanged(string propName)
{
var methods = PropertyChanged;
if(methods != null)
methods(this, new PropertyChangedEventArgs(propName));
}
<Label Content="{Binding MyData}" />
2) Set the control text via another method (or inside the property declaration):
public void SetLabel(string text)
{
label1.Content = text;
}
protected void button2_Click(object sender, RoutedEventArgs e)
{
MainWindow x = new MainWindow();
x.SetLabel("blabla");
}
The Loaded event occurs before you set MyData, change the code like this:
public partial class MainWindow : Window
{
public MainWindow(string data)
{
MyData = data
InitializeComponent();
}
Have you tried passing the value to the second window through the window's constructor?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public MainWindow(string data)
: this()
{
label1.Content = data;
}
}
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
string mytext = "blabla";
MainWindow fromloginwindow = new MainWindow(mytext);
}
}

Categories

Resources