using databinding in codebehind - c#

I have a page where I bind a command to a button. When I click it I calls a method where I get the data I want from an API.What if I don't want to only bind the data at the view but also use these data in code behind?!
Lets say this is my view :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="HelloWorld.Pages.JohnDoePage"
xmlns:local="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Pages"
xmlns:vm="clr-namespace:HelloWorld.ViewModel;assembly=HelloWorld">
<StackLayout Padding="20, 10" HorizontalOptions="Center">
<Button Command="{Binding JohnDoe}"
Text="Data about John Doe" />
</StackLayout>
</ContentPage>
the code behihnd :
Models.Info info;
public JohnDoePage(Models.Info info)
{
InitializeComponent();
BindingContext = new InfoDetailsViewModel(info);
this.info= info;
// i want to use the data here
//using the data
}
the view model :
Data _data;
public Data Data
{
get { return _data; }
set
{
if (value == _data) return;
_data = value;
OnPropertyChanged();
}
}
public ICommand JohnDoe
{
get
{
return new Command(async () =>
{
var Dataa = await _apiServices.InfoAboutJohnDOe();
});
}
}
and the service where I get the data I need is OK. I'm using the same viewmodel for binding different commands, and I don't know if this is possible by the way so I'm stuck. Any idea how can I use the data I get in the view code-behind?? Thanks in advance!!

why not just maintain a class level reference to your VM?
Models.Info info;
InfoDetailsViewModel vm;
public JohnDoePage(Models.Info info)
{
InitializeComponent();
vm = new InfoDetailsViewModel(info);
BindingContext = vm;
this.info= info;
}

Save the result of your Service call as a public property
public <TargetType> Dataa { get; set; }
and save the DataContext of your JohnDoePage as a member.
JohnDoePageViewModel dataContext = (JohnDoePageViewModel)this.DataContext;
Because then you are able to get the information from the ViewModel.
var data = dataContext.Dataa;
Does this help?

Related

complexed Issue with hiding ListView Xamarin Forms

I have a search bar with the property Text binded to a string property in my ViewModel.
I also have Behaviors within the search bar so that every time the text is changed a search is done within a list of objects using NewTextValue passed to as the query string.
The issue I have is that, I make the ListView invisible until a non-empty string is passed to my Search/Filter command (obviously.. :)). I have tried to enforcing hiding the ListView for a couple scenarios e.g. if all text is removed from the search bar.
When an item is selected from the now visible list view I used that item to populate the Text property of my SearchBar, after which I cannot hide it within code. All attempts have failed and the ListView remains visible. Note: I explicity created a hide button separately and saw it worked so I am wondering if I cannot tie hiding the view with setting the searchbar Text property.
View
<SearchBar Text="{Binding SearchText}">
<SearchBar.Behaviors>
<prismBehaviors:EventToCommandBehavior EventName="TextChanged"
Command="{Binding FilterOccupationsListCommand}"
EventArgsParameterPath="NewTextValue"/>
</SearchBar.Behaviors>
</SearchBar>
<ListView ItemsSource="{Binding FilteredOccupations}" IsVisible="{Binding FilteredOccupationsVisible}" SelectedItem="{Binding Occupation, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Please Note : My ViewModel inherits from BaseViewModel which inherits INotifyPropertyChanged. SetProperty() is what notifies the property. This is quite common with MvvmCross, Prism etc.
ViewModel
public class MyViewModel : BaseViewModel
{
public DelegateCommand<string> FilterOccupationsListCommand { get; }
public MyViewModel()
{
FilterOccupationsListCommand = new DelegateCommand<string>(FilterOccupationsList);
}
private void FilterOccupationsList(string query)
{
if (!string.IsNullOrWhiteSpace(query))
{
FilteredOccupationsVisible = true;
var searchResult = Occupations.Where(x => x.Name.ToLower().Contains(query));
FilteredOccupations = new ObservableCollection<Occupation>(searchResult);
}
else
FilteredOccupationsVisible = false;
}
private Occupation _occupation;
public Occupation Occupation
{
get => _occupation;
set
{
SetProperty(ref _occupation, value);
SearchText = value.Name;
}
}
private string _name;
public string Name { get => _name; set => SetProperty(ref _name, value); }
private string _searchText;
public string SearchText
{
get => _searchText;
set {
SetProperty(ref _searchText, value);
FilteredOccupationsVisible = false;
}
}
private bool _filteredOccupationsVisible;
public bool FilteredOccupationsVisible { get => _filteredOccupationsVisible; set => SetProperty(ref _filteredOccupationsVisible, value); }
public ObservableCollection<Occupation> _filteredOccupations = new ObservableCollection<Occupation>();
public ObservableCollection<Occupation> FilteredOccupations { get => _filteredOccupations; set { SetProperty(ref _filteredOccupations, value); } }
}
If not using Behaviors in SearchBar , you can have a try with TextChanged method of itself.
<SearchBar x:Name="MySearchBar" Text="SearchText" TextChanged="SearchBar_TextChanged" />
In ContentPage , when text cheanged fire here :
MyViewModel myViewModel = new MyViewModel();
private void SearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
Console.WriteLine("new -- " + e.NewTextValue + "-- old -- " + e.OldTextValue);
Console.WriteLine("MyEntry --" + MySearchBar.Text);
//Here can invoke FilterOccupationsList of MyViewModel
myViewModel.FilterOccupationsList(MySearchBar.Text);
}
Else if using Command to do , you need to add isntance of ICommand in MyViewModel to invoke FilterOccupationsList.
public class MyViewModel : BaseViewModel
{
public ICommand FilterOccupationsListCommand { private set; get; }
...
public MyViewModel()
{
FilterOccupationsListCommand = new Command<string>((NewTextValue) =>
{
// Pass value to FilterOccupationsList.
Console.WriteLine("SearchBar new text --" + NewTextValue);
FilterOccupationsList(NewTextValue);
});
}
...
}

How to Refresh or Recall Page on Xamarin Forms

So, I have this app where I can choose a car and see the car info... I'm displaying the cars like this.
I'm using the Rg.Plugins.Popup so when I click the car icon, it opens this popup with "my cars"
So now I'm facing a problem which is, when I choose a car, I want to refresh my current page so the car's info can be shown... I'm handling the car button click on this next view model:
public class MyCarViewModel : ViewModelBase
{
public MyCarViewModel()
{
}
public MyCarViewModel(INavigation navigation)
{
this.Navigation = navigation;
this.SelectedCar = null;
GetClientCars();
}
private Page page { get; set; }
private List<CarInfo> _CarList;
public List<CarInfo> CarList
{
get
{
return _CarList;
}
set
{
_CarList = value;
OnPropertyChanged("CarList");
}
}
private CarInfo _SelectedCar;
public CarInfo SelectedCar
{
get
{
return _SelectedCar;
}
set
{
_SelectedCar = value;
OnPropertyChanged("SelectedCar");
if (_SelectedCar != null)
{
CarSelected(_SelectedCar);
}
}
}
public INavigation Navigation { get; set; }
private void CarSelected(CarInfo car)
{
App.choosedCar = car;
PopupNavigation.Instance.PopAllAsync();
this.SelectedCar = null;
}
}
And I want this View to refresh
<views:BaseMainPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="OficinaDigitalX.Views.CarDetails"
xmlns:views="clr-namespace:OficinaDigitalX.Views">
<views:BaseMainPage.Content>
<StackLayout>
<Label Text="{Binding VID, StringFormat='Modelo: {0:F0}'}" FontAttributes="Bold"
FontSize="Large"/>
<Label Text="{Binding LicencePlate, StringFormat='MatrĂ­cula: {0:F0}'}"/>
<Label Text="{Binding Chassis, StringFormat='Chassis: {0:F0}'}"/>
<Label Text="{Binding Km, StringFormat='Ultimos Km Registados: {0:N0}'}"/>
</StackLayout>
</views:BaseMainPage.Content>
</views:BaseMainPage>
and xaml.cs
public partial class CarDetails : BaseMainPage
{
public CarDetails(CarInfo car)
{
InitializeComponent();
BindingContext = new CarDetailViewModel(this);
App.currentPage = this;
if (car != null)
{
this.Title = "Dados de " + car.MakerandModel;
}
else
{
this.Title = "Escolha uma Viatura";
}
}
}
I'm facing a lot of issues here because my car icon is a part of my "BaseMainPage" which is extended by the other Views (so the icon can be shown on all views)...
So when I click the button, the application doesn't know its current page...
I thought I might use the Navigation Stack to reload it but I don't quite know how to do this...
Hope you guys can help
Well, essentially you do not need to refresh page or reload page, you just need to refresh the data.
since you are using OnPropertyChanged(INotifyPropertyChanged) you are half way there.
instead of using List CarList use ObservableCollection CarList.
and if you deliberately want to reload the page, on dismissing the pop.up save your data and call the constructor/reinitiate the Page.
hopefully you should achieve what you are looking for.
I think you don't need to reload the page, you need to reload your data. Your page will be updated automatically with the databindings.
For me it looks like you're using Prism, so you could override the OnNavigatingTo Method and load the data every time the page is "opened".
I've just used MessagingCenter and I've called it with my OnPropertyChanged and this seemed to do the work! Thanks a lot!
View Model:
OnPropertyChanged("SelectedCar");
if (_SelectedCar != null)
{
CarSelected(_SelectedCar);
MessagingCenter.Send(this, "Hi");
}
My other view model's constructor
MessagingCenter.Subscribe<MyCarViewModel>(this, "Hi", (sender) => {
this.currentCar = App.choosedCar;
});

How can I use an array in a ViewModel?

My code looks like this right now with two lines of code for each message. The code works but if I have for example 30 messages that I can each give values to then I will need to have 60 lines of code just to declare everything:
string _msg1;
string _msg2;
public string Msg1 { get => _msg1; set => SetProperty(ref _msg1, value); }
public string Msg2 { get => _msg2; set => SetProperty(ref _msg2, value); }
and in C# I assign to these:
vm.Msg1 = "A";
vm.Msg2 = "B";
and in the XAML I bind my Text to Msg1 and another Text to Msg2
Can someone tell me how / if I can do this with array so that I would assign like this and hopefully so the assignment of the array can just be done in two lines instead of 2 lines for every single message:
vm.Msg[0] = "A";
vm.Msg[1] = "B";
For reference:
public class ObservableObject : INotifyPropertyChanged
{
protected virtual bool SetProperty<T>(
ref T backingStore, T value,
[CallerMemberName]string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = "") =>
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
You can create a simple wrapper class with indexing that supports property change notification.
For example:
public class Messages : ObservableObject
{
readonly IDictionary<int, string> _messages = new Dictionary<int, string>();
[IndexerName("Item")] //not exactly needed as this is the default
public string this[int index]
{
get
{
if (_messages.ContainsKey(index))
return _messages[index];
//Uncomment this if you want exceptions for bad indexes
//#if DEBUG
// throw new IndexOutOfRangeException();
//#else
return null; //RELEASE: don't throw exception
//#endif
}
set
{
_messages[index] = value;
OnPropertyChanged("Item[" + index + "]");
}
}
}
And, create a property in view model as:
private Messages _msg;
public Messages Msg
{
get { return _msg ?? (_msg = new Messages()); }
set { SetProperty(ref _msg, value); }
}
Now you can set or update values as:
vm.Msg[0] = "A";
vm.Msg[1] = "B";
Bindings in XAML will be same as:
<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />
Sample usage code
XAML
<StackLayout Margin="20">
<Label Text="{Binding Msg[0]}" />
<Label Text="{Binding Msg[1]}" />
<Label Text="{Binding Msg[2]}" />
<Label Text="{Binding Msg[3]}" />
<Label Text="{Binding Msg[4]}" />
<Button Text="Trigger update" Command="{Binding UpdateMessage}" />
</StackLayout>
Code-behind, view-model
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
var viewModel = new MainViewModel();
viewModel.Msg[0] = "Original message 1";
viewModel.Msg[1] = "Original message 2";
viewModel.Msg[2] = "Original message 3";
viewModel.Msg[3] = "Original message 4";
viewModel.Msg[4] = "Original message 5";
BindingContext = viewModel;
}
}
public class MainViewModel : ObservableObject
{
private Messages _msg;
public Messages Msg
{
get { return _msg ?? (_msg = new Messages()); }
set { SetProperty(ref _msg, value); }
}
public ICommand UpdateMessage => new Command(() =>
{
Msg[2] = "New message 3";
Msg[0] = "New message 1";
});
}
Arrays will not raise property changed event. You'll need to use an ObservableCollection that can raise an event when the collection has changed. However, this doesn't raise an event when the object inside the collection has changed it's value. You'll need to wrap your object, in this case a string, into a type that can raise property changed events.
Something like the following would work:
public class BindableValue<T> : INotifyPropertyChanged
{
private T _value;
public T Value
{ get => _value; set => SetProperty(ref _value, value); }
// INotifyPropertyChanged and SetProperty implementation goes here
}
private ObservableCollection<BindableValue<string>> _msg;
public ObservableCollection<BindableValue<string>> Msg
{ get => _msg; set => SetProperty(ref _msg1, value); }
you would be binding to Msg[0].Value, Msg[1].Value etc.,
Not entirely sure that I got the question, but as I understood the simplest way is this:
The Viewmodel:
Just bind to an ObservableCollection of strings, because it already implements INotifyCollectionChanged and INotifyPropertyChanged.
RelayCommand is just an implementation of ICommand and I'm assuming you have heard of them since you are doing WPF MVVM.
using System.Collections.ObjectModel;
namespace WpfApp1
{
public class MainWindowViewmodel
{
public ObservableCollection<string> Messages { get; set; }
public MainWindowViewmodel()
{
Messages = new ObservableCollection<string>();
Messages.Add("My message!");
ChangeMessageCommand = new RelayCommand(ChangeMessageExcecute);
}
public RelayCommand ChangeMessageCommand { get; set; }
private void ChangeMessageExcecute() => Messages[0] = "NEW message!";
}
}
The View:
In the view you can just bind your Textblocks to the Elements of the ObservableCollection. When you press the button, the Command gets called and changes the message in the window.
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<TextBlock Text="{Binding Messages[0]}" HorizontalAlignment="Center"/>
<Button Content="Change Message" Command="{Binding ChangeMessageCommand}" Width="200"/>
</StackPanel>
</Grid>
</Window>
Kind regards,
misdirection
I Assume that your given example is running and working as expected (Atleast with 2 items)
View Code.
Assuming you want to show all the 30 messages as a list.
<ListView ItemsSource="{Binding MessagesArray}"/>
Also you should set the DataContext properly, Comment below if you need any help
View Model Code.
We are using an ObservableCollection instead of array. Since pure arrays doesn't support proper binding features.
private ObservableCollection<string> _messagesArray;
public ObservableCollection<string> MessagesArray
{
get { return _messagesArray; }
set { SetProperty(ref _messagesArray, value); }
}
Assigning Values
MessagesArray = new ObservableCollection<string>();
vm.MessagesArray.Add("A");
vm.MessagesArray.Add("B");
In the assignment code MessagesArray = new ObservableCollection<string>(); assigns a new object of ObservableCollection of String
If you are new to ObservableCollection think of this as an wrapper to string[], but not actually true
SetProperty method will tell the XAML View that a new collection is arrived, so the UI will rerender the list.
When you call vm.MessagesArray.Add("B"); internal logics inside the method Add will tell the XAML View a new item is added to the ObservableCollection so the view can rerender the ListView with the new item.
Update 27 October 2018
You can create your own array using any of the below ways. (Not all)
string[] dataArray = new string[30];
1. this will create an array with 30 null values
string[] dataArray = { "A", "B", "C" }; //Go up to 30 items
2. this will create an array with predefined set of values, you can go up to 30
string[] dataArray = Enumerable.Repeat<string>(String.Empty, 30).ToArray();
3. this will create an array with string which holds empty values, Instead of String.Empty you can put any string value.
Choose any of the above method
I recommend the last method, then you can assign that into a Observable Collection like below.
MessagesArray = new ObservableCollection<string>(dataArray);
Now the trick is
vm.MessagesArray[0] = "A"
vm.MessagesArray[25] = "Z"
View might look like below
<TextBlock Text="{Binding MessagesArray[0]}"/>
<TextBlock Text="{Binding MessagesArray[1]}"/>
What about using reflection?
You can ask for all the public properties of type string with name "Msg*".
For example:
static class Program
{
static void Main(string[] args)
{
var vm = new MessagesViewModel();
PropertyInfo[] myProperties = vm.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.PropertyType == typeof(string) && p.Name.Contains("Msg"))
.ToArray();
foreach (var propertyInfo in myProperties)
{
//You can also access directly using the indexer --> myProperties[0]..
propertyInfo.SetValue(vm, $"This is {propertyInfo.Name} property");
}
Console.WriteLine(vm.Msg1);
Console.WriteLine(vm.Msg2);
}
}
public class MessagesViewModel
{
string _msg1;
string _msg2;
public string Msg1 { get => _msg1; set => _msg1 = value; }
public string Msg2 { get => _msg2; set => _msg2 = value; }
}
If this type of solution fits, you can wrap it with an indexer, sort the array to match the index and the Msg[num].

Why is this ListView not changing with changes to the bound property?

Basic question from a novice. I've been stuck on this and have read through a lot of material and several similar questions on SO; hopefully not a completely duplicate question. I simplified the code as much as I know how to.
I'm trying to make the ListView show a filtered ObservableCollection) property (as the ItemsSource?), based on the selection in the ComboBox.
Specifically, which "meetings" have this "coordinator" related to it.
I'm not seeing any data errors in the output while it's running and debugging shows the properties updating correctly, but the ListView stays blank. I'm trying to avoid any code-behind on the View, there is none currently.
Thanks!
public class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Meeting> meetings;
public ObservableCollection<Meeting> Meetings
{
get
{
return meetings;
}
set
{
meetings = value;
OnPropertyChanged("ListProperty");
OnPropertyChanged("Meetings");
}
}
private string coordinatorSelected;
public string CoordinatorSelected
{
get
{
return coordinatorSelected;
}
set
{
coordinatorSelected = value;
Meetings = fakeDB.Where(v => v.CoordinatorName == CoordinatorSelected) as ObservableCollection<Meeting>;
}
}
private ObservableCollection<string> comboProperty = new ObservableCollection<string> { "Joe", "Helen", "Sven" };
public ObservableCollection<string> ComboProperty
{
get
{
return comboProperty;
}
}
private ObservableCollection<Meeting> fakeDB = new ObservableCollection<Meeting>() { new Meeting("Joe", "Atlas"), new Meeting("Sven", "Contoso"), new Meeting("Helen", "Acme") };
public ObservableCollection<Meeting> ListProperty
{
get
{
return Meetings;
}
}
public class Meeting
{
public string CoordinatorName { get; set; }
public string ClientName { get; set; }
public Meeting(string coordinatorName, string clientName)
{
CoordinatorName = coordinatorName;
ClientName = clientName;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
XAML:
<Window.Resources>
<local:ViewModel x:Key="VM"></local:ViewModel>
</Window.Resources>
<DockPanel DataContext="{StaticResource ResourceKey=VM}">
<ComboBox Margin="10" ItemsSource="{Binding ComboProperty}" SelectedItem="{Binding CoordinatorSelected}" DockPanel.Dock="Top"/>
<ListView Margin="10" ItemsSource="{Binding ListProperty, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="ClientName"/>
</DockPanel>
Update:
This seems to show that the lambda is returning a Meeting object but the assignment to Meetings is failing. Is this an error in casting maybe?
Thanks again.
You always have to change a property's backing field before you fire a PropertyChanged event. Otherwise a consumer of the event would still get the old value when it reads the property.
Change the Meetings property setter like this:
public ObservableCollection<Meeting> Meetings
{
get
{
return meetings;
}
set
{
meetings = value;
OnPropertyChanged("ListProperty");
OnPropertyChanged("Meetings");
}
}
I believe I've found two solutions to the same problem. The error pointed out #Clemens was also part of the solution. The Meetings property problem is solved if I change ListProperty and Meetings to IEnumerable. Alternatively this approach without changing the type, which I believe invokes the collection's constructor with the filtered sequence as an argument.
set
{
coordinatorSelected = value;
var filteredList = fakeDB.Where(v => v.CoordinatorName == coordinatorSelected);
Meetings = new ObservableCollection<Meeting>(filteredList);
OnPropertyChanged("ListProperty");
}

SelectedItem only updates first row in database in WPF

I am developing an application to allow a user to enter their employee details of their company into a database. So far I am experimenting with WPF and trying to implement MVVM within my application while using Entity Framework.
I'm creating a Master-Detail application, and have been researching into how to achieve this using MVVM, as I'm very much new to it all.
One of the ways in which I have tried is by creating a property within my View-Model called SelectedEmployee and then binding it to a List View in my xaml, like so;
public Employee _SelectedEmployee;
public Employee SelectedEmployee
{
get
{
return _SelectedEmployee;
}
set
{
if (_SelectedEmployee == value)
return;
_SelectedEmployee = value;
OnPropertyChanged("SelectedEmployee");
}
}
<ListView HorizontalAlignment="Left" Name="listview" VerticalAlignment="Bottom" ScrollViewer.HorizontalScrollBarVisibility="Visible"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding LoadEmployee}" SelectionMode="Single" SelectedItem="{Binding SelectedEmployee, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="150" Grid.Row="1">
I then have a method that allows the user to update a SelectedItem within the List View. But this is where the problem occurs. When I select an item from the List View, it only updates the first row from the database and not the row I wanted to select.
Here's the method;
public void UpdateEmployee(Employee emp)
{
using (DBEntities context = new DBEntities())
{
emp = context.Employees.Where(e => e.EmployeeID == SelectedEmployee.EmployeeID).FirstOrDefault();
emp.Title = Title;
emp.FirstName = FirstName;
emp.Surname = Surname;
emp.Position = Position;
emp.DateOfBirth = DateOfBirth;
emp.Address = Address;
emp.Country = Country;
emp.Postcode = Postcode;
emp.PhoneNumber = PhoneNumber;
emp.MobileNumber = MobileNumber;
emp.FaxNumber = FaxNumber;
emp.Email = Email;
emp.NINumber = NINumber;
emp.ChargableResource = ChargableResource;
emp.ChargeOutRate = ChargeOutRate;
emp.TimeSheetRequired = TimeSheetRequired;
emp.WorkShift = WorkShift;
emp.BenefitsProvided = BenefitsProvided;
context.Employees.ApplyCurrentValues(emp);
context.SaveChanges();
}
}
I have bound my properties within my view model to the text-boxes within my xaml and then implementing OnPropertyChanged.
I am also using Commands to limit the amount of code-behind as its important for testability and maintainability.
Here is the command method to update;
private ICommand showUpdateCommand;
public ICommand ShowUpdateCommand
{
get
{
if (showUpdateCommand == null)
{
showUpdateCommand = new RelayCommand(this.UpdateFormExecute, this.UpdateFormCanExecute);
}
return showUpdateCommand;
}
}
private bool UpdateFormCanExecute()
{
return !string.IsNullOrEmpty(FirstName) ...
}
private void UpdateFormExecute()
{
UpdateOrganisationTypeDetail();
}
As I am new to MVVM, I'm not quite sure what I am doing wrong so would appreciate some input please :).
Then perhaps the problem is with your updating. I don't really understand what your trying to do with listview, but since it's not working in a simple datagrid this might help. it's not so much an answer as something that I wrote to find your error that happens not to contain your error. please do comment if anything is awry.
public partial class MainWindow : Window
{
private static MainViewModel _mainViewModel = new MainViewModel();
public static ObservableCollection<Employee> staff = new ObservableCollection<Employee>();
public MainWindow()
{
InitializeComponent();
this.DataContext = _mainViewModel;
dataGrid1.DataContext = staff;
listview.DataContext = staff;
Employee Employee1 = new Employee();
Employee1.name = "Jeff";
staff.Add(Employee1);
Employee Employee2 = new Employee();
Employee2.name = "Jefferson";
staff.Add(Employee2);
Employee2.name = "Tim";
}
}
public class Employee
{
public string name { get; set; }
}
public class MainViewModel : INotifyPropertyChanged
{
private string _SelectedEmployee;
public string SelectedEmployee
{
get { return _SelectedEmployee; }
set
{
_SelectedEmployee = value;
NotifyPropertyChanged("SelectedEmployee");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Categories