Notify button clicked in popup window to main window on wpf - wpf

I have two windows ,say window1 and window2(this one should be a pop up) on WPF.
What I want to do is, when a button in popup window(window2) is clicked,
I want to run method in window1.
I can achieve this by passing window1 to windows2, but I think it's not an memory-efficient way.
I have red article about routedCommand, but it's hard to understand.
I'm working on c# and any help is appreciated
Thank you

Quite often I have a static property for Current on my MainViewModel (or which ever ViewModel), and I set that property in the constructor for the ViewModel. Then from anywhere else in the application, I can get a reference to the ViewModel in question.
On the ViewModel
public MainViewModel()
{
Current = this;
}
public static MainViewModel Current { get; set; }
Anywhere else in the application:
MainViewModel.Current.DoSomething();
Routed Command
Routed commands are typically databound, and thus the command logic depends on which Data Context it is written on. If Window1's DataContext is MainViewModel, and Window2's DataContext is SecondViewModel, in order to have a button on Window2 execute a command on MainViewModel, you will have to have a reference to that instance of MainViewModel as the DataContext for the button in question.

Related

WPF best practice to get current MainWindow instance?

I got a warning that this may be a subjective question and might be closed, but I'm going to ask anyway.
I'm basically trying to access a button on my MainWindow in a WPF application from a UserControl that gets loaded up from within the MainWindow.
I'm currently accessing it like this from the UserControl's code behind:
((MainWindow)Application.Current.MainWindow).btnNext
But it does look messy, and from what I've read is not considered a best practice. Anyone able to provide an answer that constitutes a best practice for Accessing controls / properties from the current instance of a MainWindow - or any other active windows / views for that matter?
You can get a reference to the parent window of the UserControl using the Window.GetWindow method. Call this once the UserControl has been loaded:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
MainWindow parentWindow = Window.GetWindow(this) as MainWindow;
if (parentWindow != null)
{
//...
}
};
}
}
You could also access all open windows using the Application.Current.Windows property:
MainWindow mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
Which one to use depends on your requirements. If you want a reference to the application's main window for some reason, you could stick with your current approach. If you want a reference to the parent window of the UserControl, using the Window.GetWindow method would be better.
The best practice is generally to use the MVVM design pattern and bind UI controls to source properties of a view model that may be shared by several views. But that's another story. You could refer to the following link for more information about the MVVM pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx

getting values from a second window to the main window in wpf

I have a wpf application which will work minimized. The application will show a second window when system wakes up from sleep. In the second window there is a combobox and a button. when i click on the button it should set the value of a variable in the mainwindow with the value of combobox. But the problem is the variable in mainwindow is not accessible in second window. How to do this?? I searched a lot in net. But unable to find a working solution. Any suggestions??
You could use Event / delegate approach to get it:
A code snippet to sum-up:
In your First window when creating the second one do
Window1 win = new Window1();
win.GetEvent += win_GetEvent;
win.ShowDialog();
And in the second window you have:
public object ValueToGet;
public delegate object GetValueDelegate(object _value);
public event GetValueDelegate GetEvent;
public Window1()
{
InitializeComponent();
GetEvent.Invoke(ValueToGet);
}
Well I don't know which your specific requirment but just to intreduce the approach

WPF DataContext value dynamic assignment

How to set the DataContext value later in a WPF application?. Here in the below code I am setting it at the beginning (Startup). Later I would like to set another DataContext value to the view. What is the best way to do it?
public partial class App : Application
{
private void OnStartup(object sender, StartupEventArgs e)
{
MainWindow view = new MainWindow();
MainViewModel mainViewModel = new MainViewModel();
view.DataContext = mainViewModel;
view.Show();
}
}
Simply telling, there is a ObservableCollection inside the MainViewModel and it is assigned when the user do some button press action only. I need that data to be updated in the view. Please let me know if you have any questions
EDIT
::::
I have an additional question too. Do I need to reassign the entire DataContext or Can I do something through INotifyCollectionChanged event? Please clarify
Your mainViewModel is tightly coupled to your class MainViewModel. Try to use interface. you can create IViewModel and implement it to your MainViewModel. This site will help you
dofactory
you can also use some dependency injection like ninject.

Passing data to user control in MVVM pattern

Background:
I have WPF application with a main window containing a user control. I want to pass a value from the main window to the user control.
In the Main window's constructor I have code:
public MainWindow()
{
InitializeComponent();
_vm = new MainWindowViewModel();
this.DataContext = _vm;
ucControl = new UserControl1("NameSet");
}
(ucControl is my user control)
User control has two constructors:
public UserControl1()
{
InitializeComponent();
this.ID = ID.GetNewID;
}
public UserControl1(string name)
{
InitializeComponent();
_vm = new UCViewModel(name);
this.DataContext = _vm;
this.ID = ID.GetNewID;
}
The problem is: although the second constructor (with parameter) is called, it is not loaded in the main window. I checked the ID (this.ID) in the user control's loaded event and I see the ID set in the default constructor and its DataContext is null. Because of this reason, I do not get the "name" string in my user control.
Any help please? Since I am using MVVM pattern I do not want to expose properties in user control (view) to be set from main window just for this.
You are instantiating the UserControl1 object twice:
Once within the XAML. The <uc:UserControl1> element instantiates a UserControl1 object, using the default constructor, and assigns it to the member ucControl.
You instantiate it again within the constructor of the MainWindow object
If you put a break point in the constructor of UserControl, you'll notice it is called twice. I assume WPF instantiate and initialize the XAML's UserControl (#1 from above) after you assign the dynamic UserControl (#2 from above), and this is why you see the former in the logical tree of MainWindow.
You should have only one instance. If you want to parameterized a user control, the canonical paradigm is what you mention that you don't want to do (why??). If you had such a property, you could set it in the XAML: <uc:UserControl1 x:Name="..." YourProperty="NameSet>
exposing such a property is a single line in the UserControl:
public YourProperty { get; set; }
If you insist of not having this line, you should do the following:
Remove the XAML's user control.
In main window, subscribe to the Loaded event
In the handler of the Loaded event, instantiate a new UserControl1 - with whatever constructor parameter that you want.
Manually add it to the Children array of the parent Grid element
Clearly this isn't my recommendation. In addition to the complexity, with the former method you'll also work very well with the Visual Studio designer.

Access items inside the DataTemplate in WPF

I was wondering if in WPF you are able to get the actual instances of the datatemplate objects. For example in the following situation:
<UserControl>
<UserControl.Resources>
<DataTemplate x:Key="MyTemplate">
<CustomControl ></CustomControl>
</DataTemplate>
</UserControl.Resources>
<ListBox DataTemplate="{StaticResource MyTemplate}"></ListBox>
</UserControl>
Assume that CustomControl has a CustomEvent and a public CustomMethod. I want to access that event and the public method in the user control. Is this possible? How would I be able to do this? Thanks in advance for any help.
Cheers,
Nilu
You need to find the ContentPresenter holding the ListBox (by navigating the VisualTree) and then use
myDataTemplate.FindName("myCustomControl", myListBox);
There is an example on MSDN: http://msdn.microsoft.com/en-us/library/bb613579.aspx.
I don't see the ItemsSource databinding on the ListBox, so I'm assuming you left it out. If you bind to something like an ObservableCollection<> then each item in the ListBox will have it's own ViewModel class. You may have public methods on those as much as you like.
If you want an event in the custom control to be handled, handle it in code-behind in the lowest level you can, in this case in the code-behind of the UserControl.
Then, in each ViewModel have an ICommand instance (or a routed command if that suits your purpose). In the UserControl you have a DataContext which you can cast to the type of your ViewModel. So the event handler can access the ViewModel and execute Commands.
Here is Josh Smith's article on Routed Commands which you might find interesting
In this article on Apps with MVVM architecture, Josh described custom ICommands
(This is pseudo-code)
class ViewModelType {
public void DoSomething() { /* ... */ }
public ICommand DoSomethingCommand { get; set; }
public string Property { get; set; }
}
class CodeBehind {
public void EventHandler(object, args) {
(DataContext as ViewModelType).DoSomethingElseCommand.Execute();
}
}
You can create an object which attaches to the CustomControl and interacts with it.
This blogpost here illustrated some useful concepts that we can expand upon: ICommand for Silverlight with Attached Behaviors
So instead of attaching to the click event of a button (which in WPF already has a command anyways) you can create a class which attaches to your custom control.
Following the pattern in the referenced blog post you would end up with:
<CustomControl
MyNamespace:CustomControlCommand.EventCommand=
"{Binding Path=CommandHandler}" />
This would give you access to the events of the CustomControl by turning them into commands.

Resources