Good day, I'm new to WPF with MVVM, the problem in general is when filling a combox, but I'll give you some context:
I have a user control that contains different controls, including a combobox which I try to fill from the modelview but I am not successful. The user control is invoked from a main window in a few words the flow would be something like this
mainview.xaml->usercontrol.xaml->usercontrolmodelview.cs
this is where I define the source of the combobox that is inside the user control (usercontro.xaml):
<ComboBox x:Name="cbConcept" Width="150" ItemsSource="{Binding Path=Concepts}" DisplayMemberPath="textConcept" />
in this it is in usercontrolmodelview.cs linked to my user control, I define a list called Concepts that I fill it through a service (the service if it returns information and fills the list).
private IEnumerable<Concept> _concepts;
public IEnumerable<Concept> Concepts { get => _concepts; set { _concepts = value; } }
public usercontrolmodelview()
{
AddItemCommand = new ViewModelCommand(ExecuteAddCommand, ValidateAddCommand);
_api = new Api();
_memCache = new MemCache();
_ = LoadCatalogs();
}
private async Task LoadCatalogs()
{
_concepts = _memCache.GetCache<IEnumerable<Concept>>(KeysCache.CompanyCache);
if (_concepts == null)
{
_companys = await _api.GetConcept();
_memCache.SaveCache(_concepts, KeysCache.CompanyCache);
}
}
and this way I invoke the user control in my main window (xaml):
<ContentControl Content="{Binding currentChildView}"
Grid.Row="2"
Margin="20"/>
this the code in the main principal (cs):
public ICommand cmdControl { get; }
private ViewModelBase _curretnChildView;
public ViewModelBase currentChildView
{
get { return _curretnChildView; }
set
{
_curretnChildView = value;
OnPropertyChanged(nameof(currentChildView));
}
}
public MainViewModel()
{
cmdControl = new ViewModelCommand(ExecuteShowAddUserControl);
}
private void ExecuteShowAddUserControl(object obj)
{
currentChildView = new usercontrolmodelview();
}
xaml code where the command that shows the user control is linked:
<RadioButton Style="{StaticResource menuButton}"
Tag="{StaticResource colorClosed}"
Command="{Binding cmdControl}">
</RadioButton>
as extra data the user control if it is displayed in the main window.
I have tried to change the type of source by datacontext and even so the combobox is not filled
Your usercontrolmodelview should implement INotifyPropertyChanged to tell your view when a property changed and the view needs to refresh that proprety. This is espacially important when dealing with async operations.
A sample implementation could look like this:
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
I also like to create a ViewModelBase class which implements this interface and make all my viewmodels inherit from it, but this is personal preference.
In the Setter of your public IEnumerable Concepts, you call NotifyPropertyChanged(nameof(Concepts));
Please note, that if you collection of concepts might change later, you should use a ObservableCollaction and call the PropertyChangedEvent on the CollectionChanged Event handler.
Hope this helps
~BrainyXS
Related
Let's say I have two windows and a trayicon context menu. Each of the windows has a togglebutton and the context menu has a checkable menu item. All three controls are designed to display and toggle the status of the same value.
How can I bind, in this case IsChecked, of the three controls to a single global variable that when one of the controls is checked/unchecked that the other controls will update accordingly? Should I just do an invoke or is there an MVVM solution? I'm new to WPF so I'm not sure the best/most correct way to accomplish this.
Lets say you have WindowA, WindowB, ..., WindowN and assume that they all are of different type.
Create a class, lets say CommonState, that encapsulates all common properties, commands, etc. and implements INotifyPropertyChanged
public class CommonState : INotifyPropertyChanged
{
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
if (value != _isChecked)
{
_isChecked = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
Then declare an interface:
public interface ICommonStateWindow
{
CommonState { get; set; }
}
Make each window implement this interface:
public partial class WindowA : Window, ICommonState
{
public WindowA()
{
InitializeComponent();
}
// This property will be injected, do not re-assign
public CommonState CommonState { get; set; }
}
Inject the common state in each window prior to showing it, for example:
public partial class App : Application
{
private CommonState _state;
protected override void OnStartup(StartupEventArgs e)
{
_state = new CommonState() {IsChecked = true};
var wndA = new WindowA() { CommonState = _state };
var wndB = new WindowB() { CommonState = _state };
wndA.Show();
wndB.Show();
}
}
Remember to keep at least one reference to the created CommonState in some long living object (like App or the main window), so it does not get garbage collected at some point.
In the XAML you should bind using a RelativeSource, so that each new type of window you create can have its own independent ViewModel (DataContext):
<Window x:Class="Example.WindowA"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowA" Height="300" Width="300">
<Grid>
<CheckBox IsChecked="{Binding CommonState.IsChecked, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/>
</Grid>
</Window>
The example, I've demonstrated is not the only way and I won't say "the best", but it solves the following problems:
Encapsulates the common (shared) state
Synchronizes the state between different instances (or types) of windows
Allows the CommonState to be extended independently of the window implementation (only the XAML needs to be updated)
Another possible solution is to register a singleton instance of the CommonState into a statically exposed inversion of control container (IoC) and make each concrete window's ViewModel obtain an instance to it. In this way you will avoid the injection step. This would be an overkill for small projects
I anyone is trying to run the above code, remember to remove StartupUri="MainWindow.xaml" from App.xaml
You can add to your codebehind bool IsChecked property and use it for all component you want. And you can change it components' event method to true or false.
I'm having difficulties with getting a bound textbox to update. I'm still new to WPF development and I must be missing a fundamental concept as I've read nearly everything available on the internet at this point and I'm still confused. Below is my code. First, an overview of what I'm doing to better set the context for my question.
Mainwindow is a Window that contains tabs that load various pages using frame source tags. I believe this might be causing me issues as I'm not sure where the actual object is getting instantiated for each tab, just that the XAML is being loaded.
Scratchpad is a class that contains a textbox, which is going to be updated and used by almost all classes that perform any type of operation to report status and any errors.
Textbox XAML (this is in "ScratchPad_View.xaml" for context)
<TextBox x:Name="scratchMessage"
Text="{Binding Path=ScratchMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
HorizontalAlignment="Right"
Height="300"
Width ="500"
TextWrapping="Wrap"
VerticalAlignment="Top"/>
Code behind XAML
public partial class ScratchPad : Page
{
public ScratchPad()
{
InitializeComponent();
ScratchPad_Model ScratchPad_Model = new ScratchPad_Model();
this.DataContext = ScratchPad_Model;
}
}
Model Implementation
class ScratchPad_Model : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string _scratchMessage;
public string ScratchMessage;
{
get
{
return _scratchMessage;
}
set
{
if (value != _scratchMessage)
{
_scratchMessage = value;
OnPropertyChanged("ScratchMessage");
}
}
}
// Create the OnPropertyChanged method to raise the event
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Most of this I have cobbled together via responses to other questions on StackOverflow and reading numerous databinding tutorials however it's still not clicking. I'm not sure how to update the contents of the textbox and since I'm loading the page that contains the textbox in the XAML of my mainwindow I'm not sure I'm even referencing the correct object. The mainwindow loads this page in a frame tag, copied below.
<Frame Source="Common/View/ScratchPad_View.xaml" ></Frame>
In the code behind for this XAML, I have the following.
public partial class MainWindow
{
// Create scratchpad object for logging and status display
ScratchPad scratchPad = new ScratchPad();
public MainWindow()
{
InitializeComponent();
}
private void StartVault(object sender, RoutedEventArgs e)
{
// Creates the authentication prompt view object and pass the scratchPad reference for reporting
authPrompt_View _authPrompt_View = new authPrompt_View(scratchPad);
}
}
I pass the reference to the ScratchPad object that I created in the initialization of the mainwindow to all classes so that they can update the contents of the textbox, however I haven't had much luck in getting the binding to work. Once it works, I'm still not quite sure how I'm supposed to append text to the textbox. There's probably a great deal of problems here but I'm hoping to fix some of my conceptual problems and get a better understanding of what I'm doing wrong, thanks in advance!
You can use Application.Properties to set global properties for your project. So probably in SETTER method of textbox bound variable (in your case ScratchMessage), you need to set property in global application properties collection.
Below links explains it very well:
https://msdn.microsoft.com/en-us/library/aa348545(v=vs.100).aspx
http://www.c-sharpcorner.com/Resources/842/application-properties-in-wpf-and-c-sharp.aspx
My understanding is that , You have created the ViewModel for ScratchPad inside the constructor and assigning the DataContext in the same.
So, other windows will not have access to the DataContext.
My suggestion is that Maintain a base ViewModel class and inherit the base Viewmodel in all other ViewModel's.
Add ScratchMessage property inside base viewModel.
So you can access the ScratchMessage property from other viewModel's too.
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _scratchMessage;
public string ScratchMessage
{
get { return _scratchMessage; }
set
{
_scratchMessage = value;
this.OnPropertyChanged("ScratchMessage");
}
}
// Create the OnPropertyChanged method to raise the event
protected virtual void OnPropertyChanged(string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class ViewModel1 : BaseViewModel
{
ViewModel1()
{
this.ScratchMessage = "Message";
}
}
I've created an application that need a lot of access to UI controls, now what I did firstly is create an interface scalable, in particular I created different controls as UserControl and one class ViewModel that manage all method of this control for update the UI. Actually all working good in the Main thread. In particular the followin scenario working perfect:
MainWindow XAML
xmlns:MyControls="clr-namespace:HeavyAPP"
...
<!-- I use the control in the following way: -->
<Grid>
<MyControls:Scheduler x:Name="Sc"/>
</Grid>
so for example the Scheduler control contains this Data Binding:
<StackPanel Orientation="Horizontal">
<Label x:Name="NextSync" Content="{Binding NextSynchronization, IsAsync=True}" ></Label>
</StackPanel>
ViewModel structure
public class ViewModelClass : INotifyPropertyChanged
{
private CScheduler scheduler;
public ViewModelClass()
{
scheduler = new Scheduler();
}
public string NextSynchronization
{
get
{
return scheduler.GetNextSync();
}
}
}
How you can see in the ViewModel I've an instance of the Scheduler control and a property called NextSyncrhonization as the binding, so this property return a result from the method of the control instance.
For use this in the MainWindow I did the following:
public MainWindow()
{
ViewModelClass viewModel = new ViewModelClass();
DataContext = viewModel;
}
this automatically fill the control property. Now the problem's that I use a BackgroundWorker for perform some task, what I need is use the DataContext of MainWindow from different classes, (not Window, but classes).
For solve this situation I though to do something like this:
MainWindow.AppWindow.Sc.SyncLog.Dispatcher.Invoke(
new Action(() =>
{
ViewModelClass viewModel = new ViewModelClass();
var dataContext = System.Windows.Application.Current.MainWindow.DataContext;
dataContext = viewModel;
viewModel.SynchronizationLog = "this is a test from other thread"}));
now SynchronizationLog is another property that append the text to the Control, just for precision, is this:
private string _text;
public string SynchronizationLog
{
get
{
return _text += _text;
}
set
{
_text = value;
OnPropertyChanged();
}
}
this is the implementation of INotifyPropertyChanged:
`public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}`
this working only in the MainWindow, but in the external classes I can't update the UI, what am I doing wrong?
I reiceve no error, anyway.
Try the following:
extend your ViewModel as follow:
public class ViewModelClass : INotifyPropertyChanged
{
private CScheduler scheduler;
//Add this:
public static ViewModelClass Instance {get; set;} //NEW
public ViewModelClass()
{
scheduler = new Scheduler();
}
public string NextSynchronization
{
get
{
return scheduler.GetNextSync();
}
}
}
This changes your code in the xaml.cs to:
public MainWindow()
{
ViewModelClass.Instance = new ViewModelClass();
DataContext = viewModel.Instance;
}
In your external code you then DONT create a new Instance of the ViewModelClass - instead you use the existing one:
[...].Dispatcher.Invoke(() =>
{
if(ViewModelClass.Instance != null)
{
//Why you need the "var datacontext" in your example here ?
ViewModelClass.Instance.SynchronizationLog = "this is a test from other thread"
}
}));
Basically what you do here is setting a property in your ViewModel from outside of your viewModel. This can be done from everywhere.
What is different to your approach:
We dont create a new Instance of the ViewModel (different bindings in the UI aren't resetted anymore)
We created an Instance so there can always be ONLY ONE viewModel at a time
I try not to post questions like this, but i've really been struggling to find an answer or similar example. I have what I think is a really simple example I'd like to setup.
Basically I want to use commanding to add an item from a textbox to a listbox. I want to make sure there is something in the textbox via CanExecute and i want to make sure that its not already in the list.
I know this seems over complicated for what it is, but it hits on some points I've been struggling with.
<Window x:Class="Commanding_Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:Commanding_Example"
Title="MainWindow" Width="200" Height="300">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<StackPanel>
<TextBlock>Name</TextBlock>
<TextBox></TextBox>
<Button>Add</Button>
<Button>Remove</Button>
<ListBox ItemsSource="{Binding People}" DisplayMemberPath="Name"></ListBox>
</StackPanel>
</Window>
I have a Person Class
class Person
{
public string Name { get; set; }
}
The only reason I have this is that the Add needs to create a new object, so slightly more complex than a simple string.
And then a basic view model
class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
People = new ObservableCollection<Person>();
People.Add( new Person {Name = "jimmy"});
}
public ObservableCollection<Person> People { get; set; }
#region Default INotifyPropertyChanged implimentation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
So the question is, how would I implement commanding so that it uses the CanExecute to disable the Add button if the name is already there or the Name field is empty.
And then the same deal for Remove, only enabled if a name is selected in the list.
I'd like to make this as MVVM compliment as possible.
I've seen that you can do the Button.CommandBindings attached property to inject the methods you'd like to use for each, but that doesnt seem completely MVVM happy.
Also, i'd like to avoid the use of frameworks (Prism/Caliburn.Micro) since this is primarily for education reasons.
Also any references would be greatly appreciated. I've read many blogs etc but I always feel like they stray off before implementing a complete, simple example.
how would I implement commanding so that it uses the CanExecute to
disable the Add button if the name is already there or the Name field
is empty
I will show how to do the add, the remove is similar and I leave that for you to figure out. First I will show the xaml changes with the button using an AddPerson command:
<TextBox Text="{Binding CurrentPerson,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged
}"/>
<Button Command="{Binding AddPerson}">Add</Button>
We have bound the current edited text to a new property on the View Model named CurrentPerson. This is done because we want to access what the person enters, but also we need the binding updated as the user types. To accomplish that updating, we specify that the binding updates by setting the UpdateSourceTrigger attribute to be PropertyChanged. Otherwise our the CurrentPerson string and ultimately the command Can operation would only fire when the edit text box lost focus.
ViewModel
The viewmodel will subscribe to the AddPerson command. Execution of that will add the user, but also check a can method which returns a boolean whether to enable the button or not. The can will be excecuted when the CurrentPerson property changes where we ultimately call RaiseCanExecuteChanged on the commanding class to have the button check the can method.
(This VM is abbreviated for the example and based on your full VM)
public OperationCommand AddPerson { get; set; }
public string _currentPerson;
public MainViewModel()
{
People = new ObservableCollection<Person>();
People.Add(new Person { Name = "jimmy" });
// First Lamda is where we execute the command to add,
// The second lamda is the `Can` method to enable the button.
AddPerson = new OperationCommand((o) => People.Add(new Person { Name = CurrentPerson }),
(o) => (!string.IsNullOrWhiteSpace(CurrentPerson) &&
!People.Any(per => per.Name == CurrentPerson)));
// When the edit box text changes force a `Can` check.
this.PropertyChanged += MainViewModel_PropertyChanged ;
}
void MainViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "CurrentPerson")
AddPerson.RaiseCanExecuteChanged();
}
Finally here is the commanding class used which is based on my blog article Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding.:
public class OperationCommand : ICommand
{
#region Variables
Func<object, bool> canExecute;
Action<object> executeAction;
public event EventHandler CanExecuteChanged;
#endregion
#region Properties
#endregion
#region Construction/Initialization
public OperationCommand(Action<object> executeAction)
: this(executeAction, null)
{
}
public OperationCommand(Action<object> executeAction, Func<object, bool> canExecute)
{
if (executeAction == null)
{
throw new ArgumentNullException("Execute Action was null for ICommanding Operation.");
}
this.executeAction = executeAction;
this.canExecute = canExecute;
}
#endregion
#region Methods
public bool CanExecute(object parameter)
{
bool result = true;
Func<object, bool> canExecuteHandler = this.canExecute;
if (canExecuteHandler != null)
{
result = canExecuteHandler(parameter);
}
return result;
}
public void RaiseCanExecuteChanged()
{
EventHandler handler = this.CanExecuteChanged;
if (handler != null)
{
handler(this, new EventArgs());
}
}
public void Execute(object parameter)
{
this.executeAction(parameter);
}
#endregion
}
Well, MVVM is just a pattern or philosophy, so I think your desire to avoid using a framework might be a little misguided. Even if you're not using one of those frameworks, you will essentially be writing your own framework in order to implement the MVVM pattern.
That being said, probably what you want to use is a DelegateCommand or one of the similar implementations. See: http://www.wpftutorial.net/DelegateCommand.html. The important part that I think you are looking for is that the command that the WPF button is binding to must raise the CanExecuteChanged event whenever there is a change made in the view model which affects whether the command can or cannot be executed.
So in your case, for example, you would want to add a call to the CanExecuteChanged of your AddPersonDelegateCommand to your OnPropertyChanged method (possibly filtered by the name of the property that was changed). This tells anything bound to the command to call CanExecute on the command, and then you would have your logic in that CanExecute that actually determines if a person with the entered name already exists.
So to add some sample code, it might look something like this:
class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
People = new ObservableCollection<Person>();
People.Add( new Person {Name = "jimmy"});
AddPersonDelegateCommand = new DelegateCommand(AddPerson, CanAddPerson);
}
// Your existing code here
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if(propertyName == "NewNameTextBox") AddPersonDelegateCommand.RaiseCanExecuteChanged();
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
public DelegateCommand AddPersonDelegateCommand { get; set; }
public void AddPerson()
{
// Code to add a person to the collection
}
public bool CanAddPerson()
{
return !People.Any(p=>p.Name == NewNameTextBox);
}
public string NewNameTextBox
{
get { return _newNameTextBox; }
set
{
_newNameTextBox = value;
OnPropertyChanged();
}
}
}
*Note: In this sample your <TextBox></TextBox> would need to be bound to the NewNameTextBox property on the view model.
So here is the problem I'm beating my head against: I have a custom user control that exposes two dependency properties that are bound to my ViewModel. In my ViewModel I have an instance of a class that holds multiple properties that express values that relate to the user control as well as to items that control manipulates. Here's a bit of sample code to explain it visually so here is a simple sample of my control, it's a Slider that is combined with a checkbox that allows the user to lock the slider.
<custom:SliderControl IsLocked="{Binding Path=CustomClass.IsLocked, Mode=TwoWay}" SliderValue="{Binding Path=CustomClass.Value, Mode=TwoWay}" />
IsLocked and SliderValue are dependency properties that effectively manipulate the checkbox and slider that are contained in the custom control. All of the control functions work as intended, except for the bindings to the class I've defined. If I create individual properties, as in one int property and one bool property the bindings work as intended. However I have five sliders, and each slider in my actual code has five properties that tie in to them. I'm trying to eliminate code duplication by creating a class to hold these properties in a reusable object shrinking my 25 properties down to 5 class instances.
My CustomClass inherits ObservableObject and has a bool property and int property named IsLocked and SliderValue respectively. For more visual aids here is what it looks like:
public class CustomClass : ObservableObject
{
public const string SliderValuePropertyName = "SliderValue";
private int _sliderValue= 0;
public int SliderValue
{
get
{
return _sliderValue;
}
set
{
if (_sliderValue== value)
{
return;
}
_sliderValue= value;
RaisePropertyChanged(SliderValuePropertyName );
}
}
public const string IsCheckedPropertyName = "IsChecked";
private bool _isChecked = false;
public bool IsChecked
{
get
{
return _isChecked;
}
set
{
if (_isChecked == value)
{
return;
}
_isChecked = value;
RaisePropertyChanged(IsCheckedPropertyName);
}
}
The ViewModel property is very similar and looks like this, an new instance of the class is created when the ViewModel loads:
public const string SliderOnePropertyName = "SliderOne";
private CustomClass _sliderOne;
public CustomClass SliderOne
{
get
{
return _sliderOne;
}
set
{
if (_sliderOne== value)
{
return;
}
_sliderOne= value;
RaisePropertyChanged(SliderOnePropertyName );
}
}
Why won't the updating of the dependency property that is bound to the property in the class update properly? Is it because you can't properly update the class instance property by itself and instead have to update the entire class instance whenever changes occur? Or do I need to further customize the setter in this ViewModel property? As it sits now changing the slider value or checkbox never hits the bound property at all and nothing errors out when debugging.
EDIT: I've also surrounded the control in a Border and set the Border UIElement's DataContext to that of the class and then subsequently applied the more simple path binding to the underlying custom control. This however did not have any effect on my problem.
I'm a homegrown programmer so I often miss things when putting code together and I'm guessing this is the case here, unless what I'm trying just won't work.
Any help would be greatly appreciated.
EDIT: So I've been toying around with using a custom event that will let me know when the specific property of the custom control changes and then having that event wired up in my ViewModel to update the existing class. This works but still creates code duplication as now I have to have 10 events, 2 events per control, one to check for when the value of the slider changes and the other to detect when the checkbox IsChecked value changes. This code duplication exists since you can't route multiple command parameters (like a simple string identifier for which slider is being manipulated as well as the value you want to use in the code). This limitation means I can't just use 2 events that differentiate between which control is undergoing changes within the defined method as exposing the physical control to the ViewModel breaks the MVVM pattern. Using a class as the datacontext for the user control made it so I didn't care what control was being manipulated as they each had their own class instance. Using events this unravels the MVVM pattern as now I need to know which of the five controls is being manipulated by the user.
It can't be this hard to use a class in property bindings. I have to be missing something remedial.
here is a full example:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.DataContext = new ViewModel();
}
}
public class ViewModel
{
public SliderValues slv { get; private set; }
public ViewModel()
{
slv = new SliderValues();
}
}
public class SliderValues : INotifyPropertyChanged
{
bool _isLocked = false;
public bool IsLocked
{
get { return _isLocked; }
set
{
_isLocked = value;
OnPropertyChanged("IsLocked");
}
}
int _theValue = 5;
public int TheValue
{
get { return _theValue; }
set
{
_theValue = value;
OnPropertyChanged("TheValue");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string prop)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
}
Now the xaml:
<UserControl x:Class="TestBindings.MainPage"
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"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Slider Height="23" HorizontalAlignment="Left" Margin="114,138,0,0" Name="slider1" VerticalAlignment="Top" Width="100"
DataContext="{Binding slv}" Value="{Binding TheValue, Mode=TwoWay}"/>
</Grid>
</UserControl>
May be there is just a syntactical error. Try this
{Binding Path=CustomClass.IsLocked, Mode=TwoWay}
Try this...<custom:SliderControl DataContext="{Binding CustomClass}" IsLocked="{Binding IsLocked, Mode=TwoWay}" SliderValue="{Binding Value, Mode=TwoWay}" />