WPF/MVVM Abstract Common Methods - c#

SO Community, please bear with me as I am a newbie and I'm still learning(slowly). I have tried to implement absolutely every potential solution on the net with no success. I think I've completely confused myself with DependencyMethods, DependencyProperties, RelayCommands, ICommand, BaseViewModels, etc........
Here's my scenario... I have a MainWindow(MainWindow) with a Frame containing a UserControl(SampleUC). The MainWindow and UserControl DataContexts are pointed to their respective ViewModels(MainWindowVM, SampleUCVM). MainWindowVM and SampleUCVM are children of a Base ViewModel(BASEVM) which uses INotifyPropertyChanged through an ObservableCollection helper class. There is a Combobox inside SampleUC that holds the Facilities ObservableCollection constructed in SampleUCVM with method "fillFacility" and stores the SelectedFacilityNum when selected in the Combobox with the "GetFacilityNum()" method.
I would like to pull out the methods "fillFacility" and "GetFacilityNum" from the SampleUCVM and place them either in the BASEVM or a separate class where they can be accessed and used by other ViewModels. They will be used repeatedly throughout my project. Would someone be able to explain to me how to do this? Thank you for all your help and patience!
SampleUC.xaml
<Grid>
<Label Content="Facility" HorizontalAlignment="Left" Margin="10,32,0,0" VerticalAlignment="Top" Width="87" Height="27"/>
<ComboBox Name="cboFacilities"
HorizontalAlignment="Left" Margin="119,37,0,0" VerticalAlignment="Top" Width="120"
DisplayMemberPath="FacilityName"
SelectedValuePath="FacilityName"
ItemsSource="{Binding Facilities}"
SelectedValue="{Binding SelectedFacility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
</Grid>
SampleUCVM
public class SampleUCVM : BASEVM
{
#region MySQL Connection
const string dbConnectionString = #"datasource=localhost;port=3306;Initial Catalog='optest1a1';username=root;password=";
#endregion
private ObservableCollection<Facilities> _facilitiesList;
private string _selectedFacility;
private int _selectedFacilityNum;
public ObservableCollection<Facilities> Facilities
{
get { return _facilitiesList; }
set
{
SetProperty(ref _facilitiesList, value, () => Facilities);
}
}
public string SelectedFacility
{
get { return _selectedFacility; }
set
{
SetProperty(ref _selectedFacility, value, () => SelectedFacility);
if (_selectedFacility != null)
{
GetFacilityNum();
}
}
}
public int SelectedFacilityNum
{
get { return _selectedFacilityNum; }
set { SetProperty(ref _selectedFacilityNum, value, () => SelectedFacilityNum); }
}
public SampleUCVM()
{
Facilities = new ObservableCollection<Facilities>();
fillFacilities();
}
private void fillFacilities()
{
using (MySqlConnection con = new MySqlConnection(dbConnectionString))
{
Facilities = new ObservableCollection<Facilities>();
con.Open();
string Query = "SELECT * FROM facilities";
MySqlCommand createCommand = new MySqlCommand(Query, con);
MySqlDataReader dr = createCommand.ExecuteReader();
int count = 1;
while (dr.Read())
{
string FacilityName = dr.GetString(1);
Facilities facilityname = new Facilities(count, FacilityName);
Facilities.Add(facilityname);
count++;
}
con.Close();
}
}
private void GetFacilityNum()
{
if (SelectedFacility != null)
{
using (MySqlConnection con = new MySqlConnection(dbConnectionString))
{
con.Open();
string Query = "SELECT Facility_ID_Num FROM facilities WHERE Facility_Name='" + SelectedFacility + "' ";
MySqlCommand createCommand = new MySqlCommand(Query, con);
MySqlDataReader dr = createCommand.ExecuteReader();
int count = 1;
while (dr.Read())
{
int FacilityNum = dr.GetInt32(0);
SelectedFacilityNum = FacilityNum;
count++;
}
con.Close();
}
}
}
}
BASEVM
public class BASEVM : ObservableObject
{
public BASEVM()
{
}
}

I would look into implementing a data access layer for this kind of thing. For example:
public class DataAccess
{
public ObservableCollection<Facilities> GetFacilities()
{
ObservableCollection<Facilities> facilities = new ObservableCollection<Facilities>();
using (MySqlConnection con = new MySqlConnection(dbConnectionString))
{
con.Open();
string Query = "SELECT * FROM facilities";
MySqlCommand createCommand = new MySqlCommand(Query, con);
MySqlDataReader dr = createCommand.ExecuteReader();
int count = 1;
while (dr.Read())
{
string FacilityName = dr.GetString(1);
facilities facilityname = new Facilities(count, FacilityName);
facilities.Add(facilityname);
count++;
}
con.Close();
}
return facilities;
}
}
You could then include an instance of this on your ViewModel classes (or on some ViewModel base class).
With regards to your GetFacilityNum() method, this could also go into the DataAccess class, but personally I think a better solution would be to include the Facility_ID_Num as a property of your Facilities class, if possible. You would then just need to amend the GetFacilities() method to pull that in as well, but then within the application you'd always be able to access this without any database calls as it would be part of your Facilities Model.

You're making things much complex than they really are.
ObservableCollection<T> is sufficient to notify WPF controls on changes has happend to it so far; just make sure it is properly bound from XAML.
As such
public ObservableCollection<Facilities> Facilities
{
get { return _facilitiesList; }
set
{
SetProperty(ref _facilitiesList, value, () => Facilities);
}
}
is redundant and should be simplified to
public ObservableCollection<Facilities> Facilities
{
get;
}
and initialized only once - from the constructor.
As far as you want it to be at the base view model, just move the code there. Then inherit your child models from your base model and thus child would get such a property as part of themselves.
And forget about SetValue(...) unless you register your own, custom DependencyProperty which is necessary only for advanced scenarios.
Those are start points.
Have fun.

I agree with Peter Duniho your question is too broad, and there is no definite answer to it, but I would like to highlight some points to you.
What is the purpose of your BASEVM And why it inherits from ObservableObject
Class that wraps an object, so that other classes can notify for
Change events. Typically, this class is set as a Dependency Property
on DependencyObjects, and allows other classes to observe any changes
in the Value.
If you want a basic notification change functionality you could do something like this.
public class ViewModelBase:INotifyPropertyChanged{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs args)
{
PropertyChanged?.Invoke(this, args);
}
protected void RaisePropertyChanged([CallerMemberName]string propertyName = null)
{
OnPropertyChanged(propertyName);
}
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value)) return false;
storage = value;
RaisePropertyChanged(propertyName);
return true;
}
}
source
After that, you inherit from this ViewModelBase class. And when any property changed, you fire the PropertyChanged event like this:
public int SelectedFacilityNum
{
get { return _selectedFacilityNum; }
set { SetProperty(ref _selectedFacilityNum,value); }
}
I would like to pull out the methods "fillFacility" and
"GetFacilityNum" from the SampleUCVM and place them either in the
BASEVM or a separate class where they can be accessed and used by
other ViewModels
fillFacility method, as shown in your code is dealing with the database. As far as I know, in MVVM pattern, ViewModels are meant to meditate between the View and the Model
The view model acts as an intermediary between the view and the model,
and is responsible for handling the view logic. Typically, the view
model interacts with the model by invoking methods in the model
classes. The view model then provides data from the model in a form
that the view can easily use. The view model retrieves data from the
model and then makes the data available to the view, and may reformat
the data in some way that makes it simpler for the view to handle.
So, I suggest to separate the Data Access logic from your view model to a separate Data Access layer. For example, you can use the Repository pattern and create a FacilityRepository. And then you can provide this repository to the ViewModels require this functionality. And if you want to be more strict you can create IFacilityRepository interface, make the FacilityRepository implement it, and then you inject this interface to any ViewModel requires this functionality.

Related

Method Passing ViewModel vs Passing Bound Variables

I have a ComboBox bound to a ViewModel string Quality_SelectedItem.
And I have a Method named Quality, which inside accesses the value of the SelectedItem in an if statement.
I have two ways of accessing the value, by passing the ViewModel through the Method, or by passing the string Quality_SelectedItem.
Which way should I be using it and which performs faster?
XAML
<ComboBox x:Name="cboQuality"
ItemsSource="{Binding Quality_Items}"
SelectedItem="{Binding Quality_SelectedItem, Mode=TwoWay}"
HorizontalAlignment="Left"
Margin="0,2,0,0"
VerticalAlignment="Top"
Width="105"
Height="22"/>
ViewModel Class
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void OnPropertyChanged(string prop)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(prop));
}
}
// Quality Selected Item
private string _Quality_SelectedItem { get; set; }
public string Quality_SelectedItem
{
get { return _Quality_SelectedItem; }
set
{
if (_Quality_SelectedItem == value)
{
return;
}
_Quality_SelectedItem = value;
OnPropertyChanged("Quality_SelectedItem");
}
}
...
Example 1 - Passing ViewModel
In the Quality Method, I access vm.Quality_SelectedItem directly from the if statement.
public ViewModel vm = new ViewModel();
// MainWindow
public MainWindow()
{
InitializeComponent();
DataContext = vm;
// Quality Method
Quality(vm); // <---
}
// Quality Method
public static void Quality(ViewModel vm)
{
if (vm.Quality_SelectedItem == "High")
{
// do something
}
else if (vm.Quality_SelectedItem == "Low")
{
// do something
}
}
Example 2 - Passing String SelectedItem
I pass vm.Quality_SelectedItem through the Quality Method and give it the string name quality.
public ViewModel vm = new ViewModel();
// MainWindow
public MainWindow()
{
InitializeComponent();
DataContext = vm;
// Quality Method
Quality(vm.Quality_SelectedItem); // <---
}
// Quality Method
public static void Quality(string quality)
{
if (quality == "High")
{
// do something
}
else if (quality == "Low")
{
// do something
}
}
As a general rule, you should make your code as simple as possible. Remember the KISS principle. This also plays well with SOLID ("simple" is a good way to achieve Single responsibility and Interface segregation).
Avoid reaching into one object to get another.
If you need only a string value in the method, only pass that string value. Don't force your method to dig into object hierarchies and dependencies to get that value.
If the method needs to modify a string property value, then pass the object where to modify the property.
From the performance point of view, you will not notice any change. Accessing an object by-reference is a very cheap operation. (Unless you're implementing loops with billions of iterations.)
From the design point of view, keeping the things simple makes your code SOLID and easily allows re-usage.
It depends on what is //do something.
If you have to handle/interact your viewmodel-object, then pass
viewmodel as parameter
otherwise use a string for less dependencies and possibility of common use.
If you have your viewmodel as singleton, then it doesn't matter which way you go.

ViewModel properties with multiple calls to PropertyChanged

Recently I've been learning C# and WPF for work. I'm trying to use MVVM on a project I'm working on, just to keep the code organized and learn how it works.
In MVVM, controls on the View bind to properties on the ViewModel, which implements INotifyPropertyChanged. Pretty often, when a certain property is updated, I'll want a bunch of other properties to get updated as a result.
For example, I have a ListBox with a TextBox above it. You can type in the TextBox, and it filters the stuff in the ListBox. But I also need to be able to clear the TextBox from code in certain cases. The code ends up looking like this:
private Collection<string> _listOfStuff;
public Collection<string> FilteredList
{
get
{
if (String.IsNullOrWhiteSpace(SearchText))
{
return _listOfStuff;
}
else
{
return new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText)));
}
}
set
{
if (value != _listOfStuff)
{
_listOfStuff = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText"); // Tells the view to change the value of the TextBox
OnPropertyChanged("FilteredList"); // Tells the view to update the filtered list
}
}
}
As this project gets bigger, this is starting to feel sloppy. I have one setter with 6 calls to OnPropertyChanged and it's getting hard to keep track of stuff. Is there a better way to do this?
I tried out Assisticant on a project about a year ago. It figures out which of your properties need to raise notifications and also which are related. There is a good course for it on Pluralsight and the examples on the website are pretty good. If nothing else you could check out the source code to see how he did it.
Also some good suggestions from Change Notification in MVVM Hierarchies.
They mentioned:
Use an attribute -> e.g. [DependsUpon(nameof(Size))]
and
Josh Smith's PropertyObserver
Could put the raise property change calls in a method if you just need to raise the same notifications every time.
First you shouldn't do potentially expensive operations in a command, then you'll be able to remove the OnPropertyChanged("FilteredList"); from your SearchText.
So you should move that code from the getter and into it's own command and bind it from XAML (either as Command on a button or using Blends Interactivity Trigger to call it when the text fields value changes).
public ICommand SearchCommand { get; protected set; }
// Constructor
public MyViewModel()
{
// DelegateCommand.FromAsyncHandler is from Prism Framework, but you can use
// whatever your MVVM framework offers for async commands
SearchCommand = DelegateCommand.FromAsyncHandler(DoSearch);
}
public async Task DoSearch()
{
var result = await _listOfStuff.Where(x => x.Contains(SearchText)).ToListAsync();
FilteredList = new Collection<string>(result);
}
private Collection<string> _listOfStuff;
private Collection<string> _filteredList;
public Collection<string> FilteredList
{
get
{
return _filteredList;
}
set
{
if (value != _filteredList)
{
_filteredList = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get
{
return _searchText;
}
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText");
}
}
}
On a side note: You can also use OnPropertyChanged(nameof(FilteredList)); to have a refactor friendly version, when you rename your property all of your OnPropertyChanged calls will be updated to. Requires C# 6.0 though, but it's compatible with older .NET Frameworks (back to 2.0), but requires Visual Studio 2015 or later
For anyone searching for a good solution to this type of problem: Check out ReactiveUI.
It is a framework based on Reactive Extensions (Rx), with the idea that you model this type of dependencies between properties explicitly, without a jungle of RaisePropertyChanged(..).
Specifically check out the ObservableAsPropertyHelper (sometimes called OAPH).
You should only raise OnPropertyChanged in the setter of the property itself.
A cleaner implementation of your ViewModel can be:
private Collection<string> _listOfStuff;
private Collection<string> _filteredList;
public Collection<string> FilteredList
{
get
{
return _filteredList;
}
set
{
if (value != _filteredList)
{
_filteredList = value;
OnPropertyChanged("FilteredList");
}
}
}
private string _searchText;
public string SearchText
{
get { return _searchText; }
set
{
if (value != _searchText)
{
_searchText = value;
OnPropertyChanged("SearchText");
FilteredList = new Collection<string>(_listOfStuff.Where(x => x.Contains(SearchText)));
}
}
}
if you just don't wanna type only other option is to fire OnPropertyChanged for all properties which can be done by passing a null or string.Empty, although it will be sloppier code!
OnPropertyChanged(Null);
or
OnPropertyChanged(String.Empty);

How should the ViewModel refer to its Models properties?

As the ViewModel has the job to "prepare" the Model's properties to get displayed in the View, what is the best way of referring to the underlying Models properties from the ViewModel?
I could think about two solutions by now:
Option 1 - Duplicate the Model's properties in the ViewModel (wrapper-approach)
Architecture
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model-instance for this ViewModel
private Model M;
public string p1
{
get { return M.p1; }
set
{
M.p1 = value;
// assuming View controls are bound to the ViewModel's properties
RaisePropertyChanged("p1");
}
}
// let's say, I only want to check a Checkbox in the View,
// if the value of p2 exceeds 10.
// Raising the property changed notification would get handled
// in the modifying code instead of the missing setter of this property.
public bool p2
{
get
{
if (M.p2 > 10)
{ return true; }
else
{ return false; }
}
}
// Initialize the Model of the ViewModel instance in its c'tor
public ViewModel()
{ M = new Model(); }
}
Binding
<Textbox Text="{Binding p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding p2, Mode=OneWay}"/>
Advantages
Full control about how the Model's properties are displayed on the View as shown in p2: int gets converted to bool on demand.
Changes of the properties of the ViewModel could be raised individual, might be a little performance increase compared to option 2.
Disadvantages
Violation of DRY.
More Code to write/maintain.
Modifications to the Model/ViewModel could easily become shotgun surgery.
Option 2 - Treat the whole Model as property of the ViewModel
Architecture
class Model
{
public string p1 { get; set; }
public int p2 { get; set; }
}
class ViewModel : INotifyPropertyChanged
{
// Model instance for this ViewModel (private field with public property)
private Model _M;
public Model M
{
get { return _M; }
set
{
_M = value;
// Raising the changing notification for the WHOLE Model-instance.
// This should cause ALL bound View-controls to update their values,
// even if only a single property actually got changed
RaisePropertyChanged("M");
}
}
// Initialize the Model of the ViewModel instance in its ctor
public ViewModel()
{ M = new Model(); }
}
Binding
<Textbox Text="{Binding M.p1}"/>
<Checkbox IsEnabled="False" IsChecked="{Binding M.p2, Mode=OneWay, Converter={StaticResource InverseBooleanConverter}"/>
Advantages
Can save a lot of code.
Reduces complexity.
Increases maintainability.
Disadvantages
In this approach, the ViewModel is nothing more than a continuous-flow water heater for the Models properties, except for some possible interaction logic for the View.
No control about how the Model's properties are displayed in the View - which ultimately leads to total needlessness of the ViewModel and implementation of conversion logic in the View.
It is the responsibility of your ViewModel to expose the Model to the View, you should not expose the Model's properties as additional properties in the ViewModel, instead, your View should bind directly to the model.
Additionally, it isn't wrong to have logic in your Model, in fact, it makes more sense to contain model related code within the model, as opposed to the ViewModel.
Here is an example:
public class Movie
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
//Notify property changed stuff (if required)
//This is obviously a stupid example, but the idea
//is to contain model related logic inside the model.
//It makes more sense inside the model.
MyFavourite = value == "My Movie";
}
}
private bool _MyFavourite;
public bool MyFavourite
{
get { return _MyFavourite; }
set
{
_MyFavourite = value;
//Notify property changed stuff.
}
}
}
So to answer your question a little more directly, you should expose your model in the view model as a property.
public class ViewModel
{
private Movie _Model;
public Movie Model
{
get { return _Model; }
set
{
_Model = value;
//Property changed stuff (if required)
}
}
...
}
Therefore, your View will bind to the Model property, like you have already done so.
EDIT
In the example for casting to the type, you can implement a read-only property in your Model, like so:
public bool MyBool
{
get
{
return MyInt > 10; }
}
}
Now the magic here would be that you will need to call the INotifyPropertyChanged for this property whenever MyInt changes. So your other property would look something like this:
public int MyInt
{
get { ... }
set
{
_MyInt = value;
//Notify property changed for the read-only property too.
OnPropertyChanged();
OnPropertyChanged("MyBool");
}
}
In my view, Model should not have RaisePropertyChanged stuff. Some view models (e.g. Blazor) might not need it, others (e.g. WPF) might use other mechanisms like DependencyProperty. Thus, to me Model is a POCO class. Hence, it becomes ViewModel responsibility to report changes to the data up to the View. Consequently, ViewModel is bound to wrap Model's properties (OA's option 1).
You might want to look at AutoMapper to centralize the mappings.

Elegant way to implement INotifyPropertyChanged across many controls

I'm building a WPF application and I'm slowly uncovering some of the joys and also the frustrations of using WPF. My latest question involves updating the UI using INotifyPropertyChanged
My app has stacked UserControls with each UserControl containing multiple controls, so overall there are hundreds of controls which update every second providing live data. In order to update all controls I'm using something similar to below which does currently work as intended.
namespace ProjectXAML
{
public partial class ProjectX : UserControl, INotifyPropertyChanged
{
#region Declare Getter/Setter with INotifyPropertyChanged groupx3
private string m_group1Text1;
public string group1Text1
{
get
{
return m_group1Text1;
}
set
{
m_group1Text1 = value;
NotifyPropertyChanged("group1Text1");
}
}
private string m_group1Text2;
public string group1Text2
{
get
{
return m_group1Text2;
}
set
{
m_group1Text2 = value;
NotifyPropertyChanged("group1Text2");
}
}
private string m_group2Text1;
public string group2Text1
{
get
{
return m_group2Text1;
}
set
{
m_group2Text1 = value;
NotifyPropertyChanged("group2Text1");
}
}
private string m_group2Text2;
public string group2Text2
{
get
{
return m_group2Text2;
}
set
{
m_group2Text2 = value;
NotifyPropertyChanged("group2Text2");
}
}
private string m_group3Text1;
public string group3Text1
{
get
{
return m_group3Text1;
}
set
{
m_group3Text1 = value;
NotifyPropertyChanged("group3Text1");
}
}
private string m_group3Text2;
public string group3Text2
{
get
{
return m_group3Text2;
}
set
{
m_group3Text2 = value;
NotifyPropertyChanged("group3Text2");
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
/// Notifies the property changed.
private void NotifyPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#endregion
}
}
My questions are:
Is there a more elegant way to raise PropertyChanged events for lots of controls rather than lots of get/set code?
Is there a way to raise 1 PropertyChanged event covering the whole UserControl containing multiple controls instead of a separate event for every control? Is there a better method than what I'm attempting?
In strict reference to this part of your question..."Is there a way to raise 1 PropertyChanged event covering the whole UserControl containing ".
Yes, you can raise a PropertyChanged notification which says all my properties on my object are updated.
Use:
NotifyPropertyChanged(null);
then this informs the listener of INotifyPropertyChanged that all properties have changed on an object.
This isn't normally used...and can be abused....and cause inefficient updates e.g. if you were only changing a few properties and used that.
But you could argue the case for using it if you have lots of properties in your object, that you were always changing anyway at the same time...and you wanted to collapse lots of individual notifications into 1 that was raised after you had modified all properties.
Example use case (i.e. presumes you are updating all your groups in some way):
void UpdateAllGroupTextProperties()
{
group1Text1 = "groupA";
group1Text2 = "groupA2";
group2Text1 = "groupB";
group2Text2 = "groupB2";
group3Text1 = "groupC";
group3Text2 = "groupC2";
NotifyPropertyChanged(null);
}
For point 1 if you are using VS 2012 you can do the below
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
and then you can use your set property method without having to hard code the name of the properties.
Note the above code is an except of the below link
http://danrigby.com/2012/03/01/inotifypropertychanged-the-net-4-5-way/
Use the design pattern model view controler. So the model will raise the changes for you. Together with MVVM the controls will see with its dependency objects the changes and view them automatically.

Using the controls I have in one class with another class

I am new to WPF and C#. What is the best way to access the controls or objects (such as textboxes, buttons, etc) in another class. Below explains my situation. I am also using MEF if this makes a difference. Any help would be appreciated.
Thank You.
EsriMapView.xaml is where all of the objects are contained.
The class for this is EsriMapView.xaml.cs.
EsriMapViewModel.cs is the other class that I am trying to access EsriMapView.xaml from. The error I receive on all of the object is "The name blank does not exist in the current context."
Here is the code from the xaml class:
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class EsriMapView : DialogWindowBase
{
//private int? initialZoom = null;
//private double? latitude = null;
//private double? longitude = null;
//private string json = string.Empty;
//private ObservableCollection<LocationPoint> marks = null;
//private bool isZoomToBounds = false;
//private string startPoint = string.Empty;
//private string endPoint = string.Empty;
//private string searchPoint = string.Empty;
public EsriMapView()
{
InitializeComponent();
}
[Import]
public EsriMapViewModel ViewModel
{
get
{
return this.DataContext as EsriMapViewModel;
}
set
{
this.DataContext = value;
}
}
}
}
I am also using MVVM. If you need any more information, just let me know. Thanks Again.
You shouldn't be trying to access your view from your view model. This breaks one of the tenets of MVVM, which makes testing your VMs difficult. Instead, your VM should expose properties to which the view binds. The VM then has access to the data it needs to do its job.
As a simple example, suppose your view model needs to know the current zoom level in order to perform some calculation. In your view model, you would have:
public double Zoom
{
get { return this.zoom; }
set
{
if (this.zoom != value)
{
this.zoom = value;
this.RaisePropertyChanged(() => this.Zoom);
}
}
}
private void DoSomeCalculation()
{
// can use this.zoom here
}
Then, in your view:
<Slider Value="{Binding Zoom}"/>

Categories