Suppose that I've a ViewModel class with different property such as:
//MainVm will inherit ViewModel that contains IPropertyChanged implementation
public class MainVM : ViewModel
{
publi bool Foo { get; set; }
}
I instatiated this class on the main controller in this way:
MainController mc;
public MaiWindow()
{
mc = new MainController();
DataContext = mc;
InitializeComponent();
}
the MainController have this implementation:
public class MainController : MainVM
{
some methods
}
so each time I need to access to a property of MainController on each UserControls I need to do: Application.Current.MainWindow.mc.Foo
and this is't elegant at all.
Is possible access to the property of specific ViewModel without call the code line above?
Thanks.
UPDATE
For add more details and clarification to this question: so in my UserControl I need to access to the Foo property that is part of MainVM. I'm spoke about the UserControl xaml code (not the controller of the UserControl), this is an example:
public partial class ControlName : UserControl
{
public ControlName()
{
InitializeComponent();
}
public btnAdd_Click(object sender, RoutedEventArgs e)
{
//Suppose that I need to access to the property Foo of MainVM here
//I need to access to MainWindow instance like this:
Application.Current.MainWindow.mc.Foo
//isn't possible instead access to the property directly inherit the class, like:
MainVm.Foo
}
}
In order to get the configuration App-Wide, you could use the
ConfigurationManager.AppSettings["Whatever"];
These settings are located in the App.Config in the following form
<appSettings>
<add key="Whatever" value="Hello" />
</apSettings>
But as I undertand, you have a ViewModel that let Users change the settings, in this case you should go for:
Properties.Settings.Default.myColor = Color.AliceBlue;
You ViewModel could expose this property as:
public Color MyColor
{
get {
return Properties.Settings.Default.myColor;
}
set {
Properties.Settings.Default.myColor = value; RaisePropertyChanged();
}
}
public void Persist()
{
Properties.Settings.Default.Save();
// Raise whatever needed !
}
From other ViewModels you can access these setting as well:
Properties.Settings.Default.myColor
Have a look here https://learn.microsoft.com/en-us/dotnet/framework/winforms/advanced/using-application-settings-and-user-settings and here https://learn.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-create-application-settings
Related
I have a situation and I'm not sure if I'm doing it correct.
I have a ApplicationViewModel that is my "shell" for my whole application.
And within that viewmodel I have other child-ViewModels.
public ApplicationModelView()
{
ModelViewPages.Add(new GameViewModel());
ModelViewPages.Add(new EditGameViewModel());
//Set Current HomePage
CurrentPage = ModelViewPages[0];
}
#endregion
#region Properties
public BaseModelView CurrentPage
{
get { return _currentPage; }
set { _currentPage = value; OnPropertyChanged(); }
}
public List<BaseModelView> ModelViewPages
{
get
{
if (_modelViewPages == null){_modelViewPages = new List<BaseModelView>();}
return _modelViewPages;
}
}
#endregion
In my GameViewModel I display a list of objects from my model GamesModel that contains title,description etc.
When I click on an item in this list it becomes selected and then I want to change my View to EditGameViewModel with a button but I'm not sure if how to do it.
How can I get my child-ViewModel to change content in my parent-ViewModel?
Or should the child even do that?
EDIT
How I want it to function
I want when I select an item and click on button that I change from the view GameViewModel to EditGameViewModel with the data that I have selected from the list.
public void EditGame(object param)
{
//MessageBox.Show("From EditGame Function"); HERE I WANT TO CHANGE THE VIEWMODEL ON MY APPLICATIONVIEWMODEL
}
public bool CanEditGame(object param)
{
return SelectedGame != null;
}
I can offer something that works, but could be questionable. It all really depends on how you plan for your application to function.
First, similar to your MainViewModel, you want something like this:
public class MainViewModel : ObservableObject //ObservableObject being a property change notification parent
{
//Current view will always be here
public BaseViewModel ViewModel { get; set; }
public MainViewModel()
{
//By default we will say this is out startup view
Navigate<RedViewModel>(new RedViewModel(this));
}
public void Navigate<T>(BaseViewModel viewModel) where T : BaseViewModel
{
ViewModel = viewModel as T;
Console.WriteLine(ViewModel.GetType());
OnPropertyChanged("ViewModel");
}
}
Now, since we are navigating this way, every child view needs to derive from BaseViewModel.
public class BaseViewModel : ObservableObject
{
private MainViewModel _mainVM;
public BaseViewModel(MainViewModel mainVM)
{
_mainVM = mainVM;
}
protected void Navigate<T>() where T : BaseViewModel
{
//Create new instance of generic type(i.e. Type of view model passed)
T newVM = (T)Activator.CreateInstance(typeof(T), _mainVM);
//Change MainViewModels ViewModel to the new instance
_mainVM.Navigate<T>(newVM);
}
}
Now we just really need to see how we are going to have child views delegate this call of change. So we will have a BlueView.
public class BlueViewModel : BaseViewModel
{
//Relay command to call 'ToRed' function
public ICommand ChangeToRed
{
get { return new RelayCommand(ToRed); }
}
//Requires MainViewModel for BaseViewModel
public BlueViewModel(MainViewModel main) : base(main)
{
}
//Calling BaseViewModel function. Passed BaseViewModel Type
public void ToRed(object param)
{
Navigate<RedViewModel>();
}
}
And a RedView:
public class RedViewModel : BaseViewModel
{
//Relay command to call 'ToBlue' function
public ICommand ChangeToBlue
{
get { return new RelayCommand(ToBlue); }
}
//Requires MainViewModel for BaseViewModel
public RedViewModel(MainViewModel main) : base(main)
{
}
//Calling BaseViewModel function. Passed BaseViewModel Type
public void ToBlue(object param)
{
Navigate<BlueViewModel>();
}
}
Our MainWindow.xaml could look like this:
<Window.DataContext>
<viewmodels:MainViewModel/>
</Window.DataContext>
<Grid>
<ContentControl Content="{Binding ViewModel}" />
</Grid>
Doing this all children will be able to call to their parent that they would like a change. The BaseViewModel holds this parent for all children who derive, so they can pass it back and forth during navigation like a baton.
Again, Navigation all really depends on how you are using, building and planning for your application. It's not always a one size fits all way.
What i have is a user control which contains a combobox and a DataGrid , what am trying to do is Accessing the UserContorl Methods from within my other Class which is named Class1 , in the class 1 i have some methods which will take advantage of the method in the UserControl(since the user control contains necessary data like combobox.tex)
//The user control Code
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
public string Mymethod()
{
return Combobox.Text ;
}
}
// The other class is
class Class1
{
//Here i want to access the method from the withen of the userControl Class
UserControl1 cnt= new UserControl1()
//Also tried var cnt= new UserControl1()
Cnt.MyMethod()
}
What i have been trying is to create an instance of UserContorl in Class1 but i get no result since it is a new instance . Even at some point i have created a property inside the UserControl Class to pass up neccesary data but no luck as well .
You expose the form to Class1 by passing it as a parameter to the constructor:
class Class1
{
private readonly UserControl _userControl;
public Class1(UserControl userControl)
{
_userControl = userControl;
}
public void SomeMethod()
{
_userControl.MyMethod() etc
}
}
I have implemented the SelectedItem of a treeview according to the following article: Data binding to SelectedItem in a WPF Treeview
The SelectedItem works perfect and it truly reflects the item selected.
Now I want to interact with the selected item, but I'm not sure how. I can create an instance of the BindableSelectedItemBehavior class, but this is not the instance containing the data I'm looking for. How to access the class instance holding the SelectedItem of the treeview?
This is a highlight of my code:
namespace QuickSlide_2._0
{
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
...
}
public partial class Window1 : Window
{
.....
private void New_subject_Click(object sender, RoutedEventArgs e)
{
// here the code to read the instance of the class BindableSelectedItemBehavior and interact
// with the selectedItem when I click on the button
}
}
}
Maybe I'm looking totally in the wrong direction. Your help would be highly appreciated!
You want to use MVVM so that you can bind the dependency property of your behavior and then you can access the value of the SelectedItem that you made.
public class BindableSelectedItemBehavior : Behavior<TreeView>
{
//Dependency property called SelectedTreeViewItem register it
}
public partial class Window1 : Window
{
public Window1()
{
DataContext = new WindowViewModel();
}
private void New_subject_Click(object sender, RoutedEventArgs e)
{
// here the code to read the instance of the class BindableSelectedItemBehavior and interact
// with the selectedItem when I click on the button
var windowViewModel = DataContext as WindowViewModel;
var selectedItem = windowViewModel.SelectedItem;
}
}
public class WindowViewModel()
{
public object SelectedItem { get; set; } // You want to change object to the type you are expecting
}
and on your View
<TreeView>
<TreeView.Behaviors>
<BindableSelectedItemBehavior SelectedTreeViewItem="{Binding SelectedTreeViewItem,Mode=TwoWay}">
</...>
</...>
What i want to do is to create property into the model ComboBoxItemChange.cs of type ILoginView that is the interface which LoginWindow.xaml.cs is deriving. Using this property i want to grant access to the elements inside LoginWindow. I red that this is correct way to do it using MVVM pattern.
My problem is that property is always null.
LoginWindow.xaml.cs
public partial class LoginWindow : Window, ILoginView
{
public LoginWindow()
{
InitializeComponent();
this.DataContext = new ComboBoxItemChange();
(this.DataContext as ComboBoxItemChange).LoginWindow = this as ILoginView;
}
public void ChangeInputFieldsByRole(string role)
{
MessageBox.Show(role);
}
}
ComboBoxItemChange.cs
public class ComboBoxItemChange : INotifyPropertyChanged
{
public ILoginView LoginWindow { get; set; }
private void ChangeloginWindowInputFields(string value)
{
if (LoginWindow == null)
return;
LoginWindow.ChangeInputFieldsByRole(value);
}
}
ILoginView.cs
public interface ILoginView
{
void ChangeInputFieldsByRole(string role);
}
As stated in comment:
There are two different instances you are creating:
One in code behind where you set ILoginView to window itself
Second in Grid resources where you haven't set ILoginView.
Remove the instance you declared in XAML and let the bindings resolved from the instance you created in code behind. (DataContext will automatically be inherited for child controls).
If I have the following control:
public partial class MyControl : UserControl{
public string MyControlText{
get { return MyTextBox.Text; }
set { MyTextBox.Text = value; }
}
public MyControl(){ ... }
}
How can I bind to the "MyControlText" property when I place the control on one of my pages, like so:
<local:MyControl MyControlText={Binding Path=SomeField} />
Thanks!
You need to make the property a dependency property. The documentation for the DependencyProperty class shows you how to do this:
http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.aspx#