Binding command on button doesn't work wpf mvvm - c#

I'm trying to create simple add entity to database form, but binding command doesn't work and I can't figure out why. Here is XAML
<DockPanel Margin="30">
<StackPanel DockPanel.Dock="Top">
<Label>Manufacturer</Label>
<TextBox Text="{Binding Manufacturer, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label>Type</Label>
<TextBox Text="{Binding Type, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label>Serial number</Label>
<TextBox Text="{Binding SerialNumber, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Button Command="{Binding AddScaleCommand}">Add Scale</Button>
</StackPanel>
<ListBox ItemsSource="{Binding Scales}" DockPanel.Dock="Bottom"></ListBox>
</DockPanel>
And here is ScaleViewModel where the command is located
public class ScaleViewModel : ViewModel
{
public ScaleViewModel()
{
Scales = new ObservableCollection<Scale>();
}
public ICollection<Scale> Scales { get; private set; }
public string Manufacturer { get; set; }
public string Type { get; set; }
public string SerialNumber { get; set; }
public bool IsValid
{
get
{
return !string.IsNullOrWhiteSpace(SerialNumber);
}
}
public ActionCommand AddScaleCommand
{
get
{
return new ActionCommand(p => AddScale(Manufacturer, Type, SerialNumber),
p => IsValid);
}
}
private void AddScale(string manufacturer, string type, string serialNumber)
{
using (var api = new BusinessContext())
{
var scale = new Scale
{
Manifacturer = manufacturer,
Type = type,
SerialNumber = serialNumber
};
try
{
api.AddNewScale(scale);
}
catch (Exception ex)
{
//TODO kasnije
return;
}
Scales.Add(scale);
};
}
}
Scale is simple class with 3 properties (Manufacturer, type and serial number), and ViewModel class implements INotifyPropertyChanged and IDataErrorInfo and implemented necessary methods. ActionCommand class implements ICommand and implements ICommand methods.
UPDATE added ActionCommand class
public class ActionCommand : ICommand
{
private readonly Action<Object> action;
private readonly Predicate<Object> predicate;
public ActionCommand(Action<Object> action) : this(action, null)
{
}
public ActionCommand(Action<Object> action, Predicate<Object> predicate)
{
if (action == null)
{
throw new ArgumentNullException("Action", "Yout must specify an Action<T>");
}
this.action = action;
this.predicate = predicate;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
if (predicate == null)
{
return true;
}
return predicate(parameter);
}
public void Execute(object parameter)
{
action(parameter);
}
public void Execute()
{
Execute(null);
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
#endregion
}

Your ViewModel class needs to implement both IDataErrorInfo and INotifyPropertyChanged for the validation to work.
Also, there doesn't appear any way for the ActionCommand to re-evaluate IsValid() after SerialNumber has changed.
For more detail on data validation in WPF / MVVM using IDataErrorInfo, check out my blog post.

The problem was I didn't add DataContext to MainWindow in App.xaml.cs
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var window = new MainWindow
{
DataContext = new ScaleViewModel()
};
window.ShowDialog();
}
}

Related

Databinding problem in Xamarin.Forms CollectionView

I'm having trouble finding a good way of changing a property of an object inside a list using a CollectionView in Xamarin.Forms.
Below is my code (only the relevant code for readability).
I have a list which I'm databinding to a CollectionView. Each entry in the collectionview contains a label with a number and two buttons to increase and decrease that number by 1.
Note that the code below is working fine. However, I'm not satisfied with the INotifyPropertyChanged implementation in my model, which should just be a simple DTO. I'd like to remove this interface from my model along with the OnPropertyChanged. When I do that, the label with the number doesn't change anymore when I click a button.
So I should make these changes in the ViewModel, but I haven't been able to figure out how. What would be an appropriate way of implementing this in the viewmodel so I can keep my model clean with only a simple property?
Note that the BaseViewModel already implements the INotifyPropertyChanged interface.
Xaml:
<CollectionView ItemsSource="{Binding MyList}" SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Button Text="-"
Command="{Binding Source={x:Reference MyPage}, Path=BindingContext.QuantityMinusCommand}"
CommandParameter="{Binding .}" />
<Label Text="{Binding Quantity, Mode=TwoWay}" />
<Button Text="+"
Command="{Binding Source={x:Reference MyPage}, Path=BindingContext.QuantityPlusCommand}"
CommandParameter="{Binding .}" />
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Viewmodel:
public class CollectionViewModel : BaseViewModel
{
private List<MyObject> _myList = new List<MyObject>();
public ICommand QuantityMinusCommand { get; }
public ICommand QuantityPlusCommand { get; }
public CollectionViewModel()
{
QuantityMinusCommand = new Command(OnQuantityMinusCommand);
QuantityPlusCommand = new Command(OnQuantityPlusCommand);
}
public List<MyObject> MyList
{
get => _myList;
set
{
_myList = value;
OnPropertyChanged("MyList");
}
}
private void OnQuantityMinusCommand(object o)
{
var myObject = (MyObject)o;
myObject.Quantity = --myObject.Quantity;
}
private void OnQuantityPlusCommand(object o)
{
var myObject = (MyObject)o;
myObject.Quantity = ++myObject.Quantity;
}
}
Model:
public class MyObject : System.ComponentModel.INotifyPropertyChanged
{
private int _quantity;
public int Quantity
{
get => _quantity;
set
{
_quantity = value;
OnPropertyChanged("Quantity");
}
}
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
Your BaseViewModel can inherit INotifyPropertyChanged. And then your model can be a simple DTO.
public class BaseViewModel : ObservableObject
{
public BaseViewModel()
{
}
bool isBusy = false;
public bool IsBusy
{
get { return isBusy; }
set { SetProperty(ref isBusy, value); }
}
}
And the ObservableObject
/// <summary>
/// Observable object with INotifyPropertyChanged implemented
/// </summary>
public class ObservableObject : INotifyPropertyChanged
{
protected 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 void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And the model can be like this:
public class MyObject
{
public int Quantity { get; set; }
}
The viewmodel:
public class CollectionViewModel : BaseViewModel
{
// ...
}

WPF / MVVM / Model does not update viewmodel [duplicate]

This question already has an answer here:
Notifying ViewModel of Property change from Model class
(1 answer)
Closed 3 years ago.
Context:
I had a problem with binding property in my MVVM app. Now I've made a little project to test this case. It includes just window, viewmodel, model, BindableObject(abstract class with INotifyProperyChanged) and Command classes. All classes are in same namespace, datacontext is set in view, model and vm have INotifyProperyChanged, text in view is binded to vm property that is binded to model property. Constructor sets model property and it affects property in viewmodel and view.
Problem:
When I change property in model it does not change property in viewmodel and view.
Here are BaseModel and Command classes:
abstract class BindableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertieChanged ([CallerMemberName]string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
class Command : ICommand
{
private Action<object> execute;
private Func<object, bool> canExecute;
public Command(Action<object> execute, Func<object, bool> canExecute = null)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
}
Model:
public class Model : BindableObject
{
private int modelValue;
public int ModelValue { get => modelValue; set { modelValue = value; OnPropertieChanged(); } }
public Model ()
{
ModelValue = 111;
}
public void ChangeValue ()
{
ModelValue = 777;
}
}
ViewModel:
class MainVM : BindableObject
{
private int myValue;
public int MyValue { get => myValue; set { myValue = value; OnPropertieChanged(); } }
public ICommand Command1 { get; set; }
public MainVM()
{
var model = new Model();
MyValue = model.ModelValue;
Command1 = new Command( (obj) => model.ChangeValue() );
}
}
View:
<Window>
...
<Window.DataContext>
<local:MainVM/>
</Window.DataContext>
<StackPanel>
<TextBlock Text="{Binding MyValue}"/>
<Button Command="{Binding Command1}"/>
</StackPanel>
</Window>
The problem is your command in your view model is invoking a method on an instance of your model, but your xaml is binding to a separate property in your view model of type int (MyValue). That's why MyValue is getting set once in the vm constructor but never getting updated with the command.
Make the instance of your Model class a property in the view model:
private Model _myModel;
public Model MyModel
{
get
{
return _myModel;
}
set
{
_myModel = value;
OnPropertieChanged();
}
}
public ICommand Command1 { get; set; }
public MainVM()
{
MyModel = new Model();
Command1 = new Command((obj) => MyModel.ChangeValue());
}
And bind to it's ModelValue property in the xaml.
<StackPanel>
<TextBlock Text="{Binding MyModel.ModelValue}"/>
<Button Height="50" Width="100" Command="{Binding Command1}"/>
</StackPanel>
In general, though, a model class doesn't typically perform logic; rather, logic is either performed on instances of your model in a service class, or client-side in the view model. But that's a separate discussion.

WPF MVVM - Simple Binding Button with Textbox (Icommand)

What I'm trying to do is: when the textbox contains the value "123" it should enable the button and allow me to click it.
Solution Image &
View Image
I can not find a way to trigger the Button Command (Class called SpecialCommand.cs) based on my Button parameters. Could you support where I'm getting this MVVM pattern wrong?
WPF View [MainWindow.xaml]:
<Window.Resources>
<ViewModel:MainWindowVM x:Key="WindowVm"></ViewModel:MainWindowVM>
</Window.Resources>
<Grid>
<StackPanel>
<TextBox x:Name="textBox" Margin="0, 5" Text="123"/>
<Button Content="Click me!" Margin="0, 5" Command="{Binding SpecialCommand, Source={StaticResource WindowVm}}" CommandParameter="{Binding Text, ElementName=textBox, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
</StackPanel>
</Grid>
ViewModel [MainWindowVM.cs]:
public class MainWindowVM
{
private SpecialCommand _specialCommand;
public SpecialCommand SpecialCommand { get => _specialCommand; set => _specialCommand = value; }
public MainWindowVM()
{
_specialCommand = new SpecialCommand();
}
}
Command [SpecialCommand.cs]
public class SpecialCommand : ICommand
{
public bool CanExecute(object parameter)
{
if (parameter != null && (parameter as string) == "123")
return true;
return false;
}
public void Execute(object parameter)
{
MessageBox.Show("Button Pressed!");
}
public event EventHandler CanExecuteChanged;
}
What I believe, maybe this is what I'm getting wrong is since Button & Textbox are in the View I don't need add/modify any method in my SpecialCommand implementation. They should be able to see when a property is changed.
Like the CanExecuteChanged() below, this command raises a lot of times and seems overkill for this small task.
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
There is no need to make it more complicated than it needs to be.
public class MainWindowVM
{
private string m_OneTwoThree;
public string OneTwoThree{
get { return OneTwoThree; }
set {
if (m_OneTwoThree != value){
m_OneTwoThree = value;
NotifyPropertyChanged(nameof(OneTwoThree)); //if you need this let me know
}
}
}
public MainWindowVM()
{
}
public ICommand RandomCommand { get { return new RelayCommand(OnRandom, IsOneTwoThree); } }
private void OnRandom()
{
//do stuff
}
private bool IsOneTwoThree(){
if (OneTwoThree == "123"){
return true;
}
return false;
}
}
You'll also have to update your xaml I don't think it'll be able to find 'OneTwoThree' so you'll have to bind it yourself, however you usually would.
<StackPanel>
<TextBox x:Name="textBox" Margin="0, 5" Text="{Binding OneTwoThree}"/>
<Button Content="Click me!" Margin="0, 5" Command="{Binding RandomCommand, Source={StaticResource WindowVm}}"/>
</StackPanel>
If you have any questions just ask.
This is my RelayCommand : Use RelayCommand("thing to execute", "if function returns true you can execute");
public class RelayCommand : ICommand
{
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
private Action methodToExecute;
private Func<bool> canExecuteEvaluator;
public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
{
this.methodToExecute = methodToExecute;
this.canExecuteEvaluator = canExecuteEvaluator;
}
public RelayCommand(Action methodToExecute)
: this(methodToExecute, null)
{
}
public bool CanExecute(object parameter)
{
if (this.canExecuteEvaluator == null) {
return true;
}
else {
bool result = this.canExecuteEvaluator.Invoke();
return result;
}
}
public void Execute(object parameter)
{
this.methodToExecute.Invoke();
}
}
You need a way to tell the command that it should check whether it CanExecute. This is done by triggering the event CanExecuteChanged. It tells the button to requery the CanExecute property.
For this to work, I would add a text property to your view model and bind the textbox to it.
In SpecialCommand add the method:
public void TriggerCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
In the class MainWindowVM add the property:
private string _text;
public string Text
{
get { return _text; }
set {
if (value != _text) {
_text = value;
_specialCommand.TriggerCanExecuteChanged();
}
}
}
View Model to implementing INotifyPropertyChanged (see comments):
public class MainWindowVM : INotifyPropertyChanged
{
public SpecialCommand SpecialCommand { get; set; } = new SpecialCommand();
private string _text;
public string Text
{
get { return _text; }
set {
if (value != _text) {
_text = value;
OnPropertyChanged(nameof(Text));
SpecialCommand.TriggerCanExecuteChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

PropertyChanged is null wpf

Help me please!!!
I have 3 UserControls
I select user on List Users UC listbox
Then send message from SendMessage UC to Database
when i send message to Db it must refresh my chat listBox in Correspondence UC, but problem is in my ChatWrapper.
PropertyChanged in ChatWrapper is always null, and I can't refresh my ListBox in Correspondence UC with new message
List Users:
public IEnumerable<EmployeesDb> getListNames
{
get { return Db.Instance.EmployeesDbs.ToList(); }
}
static EmployeesDb m_selectedUser;
public static EmployeesDb selectedUser
{
get { return m_selectedUser; }
set
{
if (value != null)
m_selectedUser = value;
Correspondence correspondence = new Correspondence();
correspondence.CorrespondenceChat();
}
}
}
Send Message ( I try to refresh -> SendInfo.FirstOrDefault().RefreshGUI();)
public static DependencyProperty SendInfoProperty =
DependencyProperty.Register(
"SendInfo",
typeof(IEnumerable<ChatWrapper>),
typeof(SendMessage));
public IEnumerable<ChatWrapper> SendInfo
{
get { return GetValue(SendInfoProperty) as IEnumerable<ChatWrapper>; }
set { SetValue(SendInfoProperty, value); }
}
void SendMessageCommandExecute()
{
//...
SendInfo.FirstOrDefault().RefreshGUI();
//...
}
ChatWrapper
public class ChatWrapper : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void FirePropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
public void RefreshGUI()
{
FirePropertyChanged("message");
}
public ChatDb chatDb { get; set; }
public string message
{
get
{
return (chatDb != null) ? string.Format("{0} {1}.{2} / {3} / {4}\n{5}",
chatDb.FromEmployeesDb.surname,
chatDb.FromEmployeesDb.name[0],
chatDb.FromEmployeesDb.middleName[0],
chatDb.messageDateTime,
chatDb.computerName,
chatDb.message) : null;
}
}
Correspondence
//...
public partial class Correspondence : UserControl, INotifyPropertyChanged
{
public static DependencyProperty GetCorrespondenceInfoProperty =
DependencyProperty.Register(
"GetCorrespondenceInfo",
typeof(IEnumerable<ChatWrapper>),
typeof(Correspondence),
new PropertyMetadata(OnChanged));
public IEnumerable<ChatWrapper> GetCorrespondenceInfo
{
get { return GetValue(GetCorrespondenceInfoProperty) as IEnumerable<ChatWrapper>; }
set { SetValue(GetCorrespondenceInfoProperty, value); }
}
static void OnChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var me = d as Correspondence;
me.chat = me.GetCorrespondenceInfo;
}
ICollectionView m_CollectionView;
public static IEnumerable<ChatWrapper> m_chat;
public IEnumerable<ChatWrapper> chat
{
get { return m_chat; }
set
{
m_chat = value;
if (ListUsers.selectedUser != null)
CorrespondenceChat();
FirePropertyChanged("chat");
}
}
public void CorrespondenceChat()
{
if (m_chat == null)
return;
m_CollectionView = CollectionViewSource.GetDefaultView(m_chat);
//...
FirePropertyChanged("chat");
}
XAML of Correspondence (refresh
<Grid>
<ListBox x:Name="correspondenceListBox" ItemsSource="{Binding chat, RelativeSource={RelativeSource AncestorType={x:Type local:Correspondence}}}"
Height="auto" Grid.Row="0" Grid.Column="1" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" >
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding message}" TextWrapping="Wrap" Width="auto"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I tried to write
public event PropertyChangedEventHandler PropertyChanged = delegate { };
PropertyChanged is no longer null, but it's still not updated

textbox input to get / set viewmodel

I'm sure this has already been asked, but I'm still new to MVVM and WPF, and not too sure what I should be searching for.
I have a viewmodel which includes items in a Model, as well as some additional temporary data items which will all be passed to a process.start(). I have a stackpanel of textbox, and want to allow the user to type in a "ModelName", and if existing, The ViewModel will get and set "TemplateName" associated with the ModelName.
I'm a bit lost on how to implement this. Do I need to create a completely separate ViewModel, which then goes and extracts data from ModelViewModel? Do I just write some code under ModelName's set, where it can validate, query, and set TemplateName?
Model:
public partial class Model
{
public string ModelName { get; set; }
public virtual Template Template { get; set; }
and ViewModel, which takes the Model, and some temporary data:
public class LauncherViewModel:ViewModelBase
{
public LauncherViewModel()
{
_ESTContext = new ESTContext();
Models = new ObservableCollection<Model>(_ESTContext.Models);
}
private ESTContext _ESTContext;
private string _modelname;
private string _serialno;
private string _sonumber;
private string _templatename;
private string _outputname;
private Model _selectedmodel;
public ObservableCollection<Model> Models { get; set; }
public string ModelName
{
get { return _modelname; }
set
{
if (!string.Equals(_modelname, value))
{
_modelname = value;
};
}
}
public string TemplateName { get { return _templatename; }}
public string SerialNo { get { return _serialno; } }
public string SONumber { get { return _sonumber; } }
public string OutputName { get { return _outputname; } }
public Model SelectedModel
{
get { return _selectedmodel; }
set
{
if (_selectedmodel != value)
{
_selectedmodel = value;
}
}
}
}
My View:
<DockPanel>
<StackPanel Margin="0,78,0,68" Width="233" DataContext="{Binding Models}">
<ComboBox IsEditable="True" Text="{Binding ModelName}" SelectedItem="{Binding SelectedModel}"/>
<TextBox Height="23" TextWrapping="Wrap" Text="{Binding SONumber}"/>
<TextBox Height="23" TextWrapping="Wrap" Text="{Binding SerialNumber}"/>
<Button Content="Button"/>
</StackPanel>
</DockPanel>
For your gui to update you must implement INotifyPropertyChanged and a call to it on all your bound properties.
// basic base class for your models, you a
public class ModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator] // remove if you are not using R#
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
// your model
public class Model : ModelBase
{
private string modelName;
private Template template;
public string ModelName
{
get { return modelName; }
set
{
if (value == modelName) return;
modelName = value;
OnPropertyChanged();
}
}
public virtual Template Template
{
get { return template; }
set
{
if (Equals(value, template)) return;
template = value;
OnPropertyChanged();
}
}
}
View:
<DockPanel>
<StackPanel Margin="0,78,0,68" Width="233">
<ComboBox IsEditable="True" Text="{Binding ModelName, Mode='TwoWay'}" SelectedItem="{Binding SelectedModel}" ItemsSource="{Binding Models}"/>
<TextBox Height="23" TextWrapping="Wrap" Text="{Binding SONumber Mode='TwoWay'}"/>
<TextBox Height="23" TextWrapping="Wrap" Text="{Binding SerialNumber Mode='TwoWay'}"/>
<Button Content="Button"/>
</StackPanel>
Note the Mode='TwoWay' this makes the GUI change the values in your viewmodel, rather than just display them. So you need to set that on everything that's supposed to be editable as above. The default behaviour of WPF is that when a control looses focus it will update the bound property, if you set UpdateSourceTrigger='PropertyChanged' the property will be updated each time ie a letter is entered in a text box. I'll leave that part to you, but you will have to do it in your vm! At minimum the properties SONumber,SerialNumber and Models(if it's ref. changes).
VM: I assume you use galasoft here
public class LauncherViewModel : ViewModelBase
{
private ESTContext _ESTContext;
private string _templatename;
private string _modelname;
private string serialNumber;
private string _outputname;
private string modelName;
private ObservableCollection<Model> models;
private Model selectedModel;
private string soNumber;
public LauncherViewModel()
{
// dangerous ;)
_ESTContext = new ESTContext();
Models = new ObservableCollection<Model>(_ESTContext.Models);
}
public ObservableCollection<Model> Models
{
get { return models; }
set
{
if (Equals(value, models)) return;
models = value;
RaisePropertyChanged();
}
}
public string ModelName
{
get { return modelName; }
set
{
if (value == modelName) return;
modelName = value;
RaisePropertyChanged();
}
}
public string TemplateName { get { return _templatename; }}
public string SerialNumber // Note you spelled this wrong in your xaml. SONumber
{
get { return serialNumber; }
set
{
if (value == serialNumber) return;
serialNumber = value;
RaisePropertyChanged();
}
}
public string SONumber
{
get { return soNumber; }
set
{
if (value == soNumber) return;
soNumber = value;
RaisePropertyChanged();
}
}
public string OutputName { get { return _outputname; } }
public Model SelectedModel
{
get { return selectedModel; }
set
{
if (Equals(value, selectedModel)) return;
selectedModel = value;
RaisePropertyChanged();
}
}
}
A cool litle thing if you are using galasoft or sim together with R#.
public class YourViewModelBase : ViewModelBase
{
[NotifyPropertyChangedInvocator] // alt + enter = convert auto property to prop
// with backing field and change notification :)
override protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
base.RaisePropertyChanged(propertyName);
}
// .. :)
}
Cheers,
Stian
If I havent misunderstood your question , Bind Models to ItemsSource of ComboBox instead of Binding it to DataContext of StackPanel
Remove DataContext binding
<StackPanel Margin="0,78,0,68" Width="233" >
Bind Itemssource of ComboBox to Models and you will also have to specify DisplayMemberPath to the property of Model that you want to display in ComboBox.
<ComboBox IsEditable="True" ItemsSource="{Binding Models}" Text="{Binding ModelName}" SelectedItem="{Binding SelectedModel}"/>
And I am assuming you are setting DataContext of window to instance of LauncherViewModel class.
You need to raise the property changed event on properties you bind to i.e.:
private string _ModelName;
public string ModelName
{
get { return _ModelName; }
set
{
if (_ModelName != value)
{
_ModelName = value;
RaisePropertyChanged("ModelName");
}
}
}
In your base view model you need something like this (make sure you implement INotifyPropertyChanged):
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
In the constructor or loaded event of your view add this:
DataContext = new LauncherViewModel();

Categories

Resources