I looked around the web for an answer, but can't seem to get this to work. Here is what I have:
public class UIValues : INotifyPropertyChanged
{
private double zoomValue = 1;
private static readonly UIValues instance = new UIValues();
public event PropertyChangedEventHandler PropertyChanged;
internal static UIValues Instance { get { return instance; } }
internal double ZoomValue
{
get { return zoomValue; }
set
{
if (this.zoomValue == value)
return;
this.zoomValue = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("ZoomValue"));
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, e);
}
}
and then I have this:
<UserControl>
<UserControl.DataContext>
<local:UIValues x:Name="uiValues"/>
</UserControl.DataContext>
.
.
.
<Viewbox x:Name="vbViewBox" RenderTransformOrigin="0.5,0.5">
<local:ImageControl x:Name="imgControl" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Viewbox.RenderTransform>
<TransformGroup>
<CompositeTransform x:Name="trCompositeTransform" ScaleX="{Binding ZoomValue}" ScaleY="{Binding ZoomValue}" Rotation="0" SkewX="0" SkewY="0"/>
</TransformGroup>
</Viewbox.RenderTransform>
</Viewbox>
</UserControl>
So basically, whenever I make a change to the ZoomValue from the UIValues class from code-behind, the UI is not updated.
Anyone know why?
Thanks!
Looking at the posted code I'll have a guess that you have something like this to change the Zoom Value.
UIValues.Instance.ZoomValue = x;
The problem is this xaml:-
<local:UIValues x:Name="uiValues"/>
constructs an independent instance of UIValues that is not the same instance returned by your static Instance property. Hence you will be changing a value on a object that nothing is listening to.
Edit
Also ZoomLevel is internal, for it work with binding is must be public.
The solution is to use IApplicationService and do things through App.xaml.
Change you class to:
public class UIValues : INotifyPropertyChanged, IApplicationService
{
private double zoomValue = 1;
public event PropertyChangedEventHandler PropertyChanged;
internal static UIValues Instance { get; private set; }
public double ZoomValue
{
get { return zoomValue; }
set
{
if (zoomValue == value)
return;
zoomValue = value;
this.OnPropertyChanged(new PropertyChangedEventArgs("ZoomValue"));
}
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, e);
}
void IApplicationService.StartService(ApplicationServiceContext context)
{
Instance = this;
Application.Current.Resources.Add("UIValues", Instance);
}
void IApplicationService.StopService() { }
}
Add the instance of UIValues to App.Xaml:-
<Application.ApplicationLifetimeObjects>
<local:UIValues />
</Application.ApplicationLifetimeObjects>
Then set the user control DataContext like this:-
<UserControl ... DataContext="{StaticResource UIValues}">
That said this is waste of the DataContext which you may need to bind to real data. You can specify the Source directly on the bindings instead:-
<CompositeTransform ScaleX="{Binding ZoomValue, Source={StaticResource UIValues}}" ScaleY="{Binding ZoomValue, Source={StaticResource UIValues}}" Rotation="0" SkewX="0" SkewY="0"/>
Change access modifier for ZoomValue property to public and everything will work fine.
Related
I know there are a lot of similar questions and I spent two hours by now trying to implementing them but can't proceed. So the problem seems simple. When I don't have a viewmodel, I can set the datacontext to a class and it is very easy to transfer data with that class. But when there is viewmodel, I have to set the datacontext to that and can't find a way to return any value after that. I tried to implement countless solutions to the problem but it seems that they are above my skill level. Thank you so much for your help!
The important parts of my code (its a simple game which i want to save, where save is named by userinput) The first window, where I want to get data from the second window
case Key.Escape: {
Thread t = new Thread(() => {
SaveGameWindow pw = new SaveGameWindow(); //the second window
if ((pw.ShowDialog() == true) && (pw.Name != string.Empty)) //pw.Name always empty
{
ILogicSaveGame l = new LogicSaveGame();
l.Write(pw.Name, "saved_games.txt");
MessageBox.Show("game saved");
}
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
XAML (from now on everything belongs to the SaveGameWindow):
<Window.Resources>
<local:SaveGameViewModel x:Key="my_viewmodel"/>
</Window.Resources>
<Grid DataContext="{StaticResource my_viewmodel}">
<TextBox Text="{Binding Name}"/> //i want to acces this in the first window
<Button Command="{Binding CloseCommand}"
Content="Save"/>
Code behind:
private readonly SaveGameViewModel vm;
public SaveGameWindow()
{
this.InitializeComponent();
this.vm = this.FindResource("my_viewmodel") as SaveGameViewModel;
if (this.vm.CloseAction == null)
{
this.vm.CloseAction = new Action(() => this.Close());
}
}
Viewmodel
public class SaveGameViewModel : ViewModelBase
{
public SaveGameViewModel()
{
this.CloseCommand = new RelayCommand(() => this.Close());
}
public string Name { get; set; }
public ICommand CloseCommand { get; private set; }
public Action CloseAction { get; set; }
private void Close()
{
this.CloseAction();
}
}
I use galasoft mvvmlightlibs
There are many solutions to this problem. The simplest solution is to use a shared view model for both windows and data binding. Since both windows would share the same DataContext, both have access to the same data or model instance by simply referencing their DataContext property.
But if you prefer to have individual view models, you would choose a different solution.
Solution 1
If you want to use a dedicated view model for each window, you can always use composition and make e.g. an instance SaveGameViewModel a member of MainWindowViewModel. Any class that has access to MainWindowViewModel will also have access to the SaveGameViewModel and its API, either directly or via delegating properties.
This example uses direct access by exposing SaveGameViewModel as a public property of MainWindowViewModel:
SaveGameViewModel.cs
public class SaveGameViewModel : INotifyPropertyChanged
{
private string name;
public string Name
{
get => this.name;
set
{
this.name = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
MainWindowViewModel.cs
public class MainWindowViewModel : INotifyPropertyChanged
{
public SaveGameViewModel SaveGameViewModel { get; set; }
// Allow to create an instance using XAML
public MainWindowViewModel() {}
// Allow to create an instance using C#
public MainWindowViewModel(SaveGameViewModel saveGameViewModel)
=> this.SaveGameViewModel = saveGameViewModel;
}
App.xaml
<Application>
<Application.Resources>
<MainWindowViewModel x:Key="MainWindowViewModel">
<MainWindowViewModel.SaveGameViewModel>
<SaveGameViewModel />
</MainWindowViewModel.SaveGameViewModel>
</MainWindowViewModel>
</Application.Resources>
</Application>
SaveGameWindow.xaml
<Window DataContext="{Binding Source={StaticResource MainWindowViewModel}, Path=SaveGameViewModel}">
<TextBox Text="{Binding Name}" />
<Window>
MainWindow.xaml
<Window DataContext="{StaticResource MainWindowViewModel}">
<Window>
MainWindow.xaml.cs
partial class MainWindow : Window
{
private void OnKeyPressed(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
var mainWindowViewModel = this.DataContext as MainWindowViewModel;
string saveGameName = mainWindowViewModel.SaveGameViewModel.Name;
}
}
}
Solution 2
Since you are just showing a dialog, you can store the current instance of the SaveGameViewModel or its values of interest after the dialog has been closed:
MainWindow.xaml.cs
partial class MainWindow : Window
{
private SaveGameViewModel CurrentSaveGameViewModel { get; set; }
private bool IsSaveGameValid { get; set; }
private void ShowDialog_OnSaveButtonClick(object sender, RoutedEventArgs e)
{
var saveGameDialog = new SaveGameWindow();
this.IsSaveGameValid = saveGameDialog.ShowDialog ?? false;
this.CurrentSaveGameViewModel = saveGameDialog.DataContext as SaveGameViewModel;
}
private void OnKeyPressed(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape && this.IsSaveGameValid)
{
string saveGameName = this.CurrentSaveGameViewModel.Name;
}
}
}
MainWindow.xaml
<Window>
<Window.DataContext>
<MainWindowViewModel />
</Window.DataContext>
<Window>
SaveGameWindow.xaml
<Window>
<Window.DataContext>
<SaveGameViewModel />
</Window.DataContext>
<TextBox Text="{Binding Name}" />
<Window>
I am struggling with this for a while and I cannot figure it out. I have a button and a textBox. The textBox is linked to a property named: MessageDisplay. I want to be able to access this property and update the textBox in several places. Sadly, the PropertyChanged is null. The weird thing is that if I copy/paste the MessageDisplayModel class into the *MessageViewModel * class, it works ...
here is my code :
XAMLfile :
<Grid>
<Button Command="{Binding DisplayTextCommand}" Name="DisplayTextCommand" Margin="53,72,544.6,286" Width="Auto">Push</Button>
<TextBox Name="MessageDisplay" Text="{Binding MessageDisplay, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" />
</Grid>
MessageDisplayModel file
public class MessageDisplayModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _message;
public string MessageDisplay
{
get { return _message; }
set
{
this._message = value;
this.OnPropertyChanged("MessageDisplay");
}
}
public void UpdateTextBox(string output)
{
MessageDisplay = output;
}
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
}//class
MessageViewModel file:
public class MessageViewModel
{
private ICommand _testCommand;
public MessageDisplayModel MessageDisplaySmt = new MessageDisplayModel();
public ICommand DisplayTextCommand
{
get
{
return new DelegateCommand(DisplayMessage);
}
set
{
if (_testCommand == value) return;
_testCommand = value;
}
}
public void DisplayMessage()
{
MessageDisplaySmt.UpdateTextBox("Successfuly downloaded");
}
}//class
MainWindow file
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MessageDisplay.DataContext = new MessageDisplayModel();
DisplayTextCommand.DataContext = new MessageViewModel();
}
}//class
I update the MessageDisplay property by using the method UpdateTextBox(string). I call this method on the click of the button. When debugging the property gets updated but when time comes to notify the UI that the property has changed, PropertyChangedEventHandler PropertyChanged has its value null ... But if I write something in the textBox, the PropertyChangedEventHandler PropertyChanged gets changed and isn't null anymore. All I want is to be able to change the textBox's property whenever I want and from anywhere I want to.
Thank you
You are using two different instances of MessageDisplayModel. You must use a shared instance.
Also the DisplayTextCommand is implemented "wrong". The set method is redundant as the property's get always returns a new instance of the ICommand.
MessageViewModel.cs
public class MessageViewModel
{
pulic MessageViewModel()
{
}
pulic MessageViewModel(MessageDisplayViewModel messageDisplayViewModel)
{
this.MessageDisplaySmt = messageDisplayViewModel;
}
public void DisplayMessage()
{
this.MessageDisplaySmt.UpdateTextBox("Successfuly downloaded");
}
public MessageDisplayViewModel MessageDisplaySmt { get; set; }
public ICommand DisplayTextCommand { get => new DelegateCommand(DisplayMessage); }
}
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Alternatively use XAML to set the DataContext (see MainWindow.xaml). Would require a parameterless constructor.
this.DataContext = new MessageViewModel(new MessageDisplayViewModel());
}
}
MainWindow.xaml
<Window>
<!--
Alternative DataContext declaration using XAML instead of C#.
Requires a parameterless constructor for both view model objects.
-->
<Window.DataContext>
<MessageViewModel>
<MessageViewModel.MessageDisplaySmt>
<MessageDisplayViewModel />
</MessageViewModel.MessageDisplaySmt>
</MessageViewModel>
</Window.DataContext>
<StackPanel>
<Button Command="{Binding DisplayTextCommand}"
Content="Push" />
<TextBox Text="{Binding MessageDisplaySmt.MessageDisplay}" />
</StackPanel>
</Window>
I'm trying to make a control that has a current value with an optional equation string.
I have 2 textboxes:
One (a) where you can enter an equation shortcut to a value to put into the other (b).
(b) contains the actual value.
(for example, in (a), if you enter 'pi', the second will then fill with "3.1415926535897931")
I'm using 2 textboxes so the user can refine their equation if they need to, and watch the value change as they modify it.
The data has 2 fields, one being the equation string and the other being the current value.
so I have (a).Text bound to the string, a new property on (a) that holds the value, and I bind (b).Text to the value also.
(a).Text is TwoWay
(a).Value is OneWayToSource (since changes to the text should only be pushed to b)
(b).Value is TwoWay
This all works fine if I have the data set in the constructor before any XAML binding, but does not work at all if I add the data after binding.
Here is a minimal amount of code that shows the problem.
The only comment is at the line that can make it work or not.
As a last resort I could turn it into a custom control and handle it in the code-behind, but I'd think this should work in the first place.
Any ideas why this isn't working?
Thanks!
Here is the XAML:
<Window x:Class="twoBindingsOnSameField.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:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:twoBindingsOnSameField"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button Content="load data" Click="Button_Click" Width="80" IsEnabled="{Binding NeedsData}"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="enter text:" Width="80"/>
<local:TextBoxCalc Text="{Binding Item.ItemString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextBoxCalculatedValue="{Binding Item.ItemValue, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
Width="200"
IsEnabled="{Binding HasData}"
/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="updated text:" Width="80"/>
<TextBox Text="{Binding Item.ItemValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Width="200"
IsEnabled="{Binding HasData}"
/>
</StackPanel>
</StackPanel>
</Window>
Here is the codebehind.
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
namespace twoBindingsOnSameField
{
public partial class MainWindow : Window
{
data data;
public MainWindow()
{
InitializeComponent();
data = new data();
/// ---- Does not work with the following line commented out, but does if it is uncommented ----
/// ---- use the button to set the data ----
//setdata();
DataContext = data;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
setdata();
}
void setdata()
{
if (data.Item == null)
data.Item = new dataitem();
}
}
public class data : notifybase
{
dataitem item;
public data()
{
}
public dataitem Item
{
get
{
return item;
}
set
{
if (item != value)
{
item = value;
notifyPropertyChanged("Item");
notifyPropertyChanged("HasData");
notifyPropertyChanged("NeedsData");
}
}
}
public bool HasData
{
get
{
return Item != null;
}
}
public bool NeedsData
{
get
{
return Item == null;
}
}
}
public class dataitem : notifybase
{
string itemString;
string itemValue;
public dataitem()
{
itemString = "3";
itemValue = "4";
}
public virtual string ItemString
{
get
{
return this.itemString;
}
set
{
if (!object.Equals(this.itemString, value))
{
this.itemString = value;
notifyPropertyChanged("ItemString");
}
}
}
public virtual string ItemValue
{
get
{
return this.itemValue;
}
set
{
if (!object.Equals(this.itemValue, value))
{
this.itemValue = value;
notifyPropertyChanged("ItemValue");
}
}
}
}
public class TextBoxCalc : TextBox
{
public TextBoxCalc()
{
TextProperty.AddHandler(this, (o,e)=>TextBoxCalculatedValue="updated:" + Text);
}
#region TextBoxCalculatedValue
public static DependencyProperty TextBoxCalculatedValueProperty = DependencyProperty.Register("TextBoxCalculatedValue", typeof(string), typeof(TextBoxCalc), new PropertyMetadata(""));
public string TextBoxCalculatedValue
{
get
{
return (string)GetValue(TextBoxCalculatedValueProperty);
}
set
{
if (!object.Equals(TextBoxCalculatedValue, value))
SetValue(TextBoxCalculatedValueProperty, value);
}
}
#endregion
}
public class notifybase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null)
PropertyChanged(this, e);
}
protected virtual void notifyPropertyChanged(string propertyName)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
OnPropertyChanged(e);
}
}
static class extensions
{
public static void AddHandler(this DependencyProperty prop, object component, EventHandler handler)
{
DependencyPropertyDescriptor dpd = DependencyPropertyDescriptor.FromProperty(prop, component.GetType());
if (dpd != null)
dpd.AddValueChanged(component, handler);
}
}
}
The reason why it works when you uncomment //setdata(); is because it is initializing the object in what is effectively your viewmodel, therefore you can change its properties via binding. To clarify as a side note, data would be your view model, and dataitem is your model, however you're dataitem is using INPC, so it doesn't really make sense in this case to have a viewmodel necessarily.
Anyways, the issue is that TextBoxCalculatedValue is set to a OneWayToSource binding. When you run the code commented out, its going to try and bind to a null value. When it does, it tries to update a null value, which isn't possible. WPF handles what would normally be a null exception automatically. When you update the dataItem by clicking the button, it doesn't update the object TextBoxCalc is bound to, so instead, it will continue trying to bind & update the null object. Change it to a TwoWay binding and you'll see a difference. Changing to TwoWay is probably your best option.
Good practice is to use constructor injection to practice dependency injection. With that being said, passing a dataItem to data would be the best route, and at the very least, initializing dataItem in data's constructor would be an ideal approach. So,
public data(dataItem item)
{
Item = item;
}
or
public data()
{
Item = new dataitem();
}
This question already has answers here:
Binding to static property
(12 answers)
Closed 2 years ago.
I had a variable which was not static and INotifyPropertyChanged implemented succesfully. Then I tried to make it global, so turned it a static variable. But this time, INotifyPropertyChanged does not work. Any solution?
INotifyPropertyChanged works on instance properties. One solution is to use a singleton pattern and keep INotifyPropertyChanged, the other is to use your own event to notify listeners.
Singleton example
public sealed class MyClass: INotifyPropertyChanged
{
private static readonly MyClass instance = new MyClass();
private MyClass() {}
public static MyClass Instance
{
get
{
return instance;
}
}
// notifying property
private string privMyProp;
public string MyProp
{
get { return this.privMyProp; }
set
{
if (value != this.privMyProp)
{
this.privMyProp = value;
NotifyPropertyChanged("MyProp");
}
}
}
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(info));
}
}
}
EDIT: In WPF 4.5, they introduced property changed mechanic for static properties:
You can use static properties as the source of a data binding. The
data binding engine recognizes when the property's value changes if a
static event is raised. For example, if the class SomeClass defines a
static property called MyProperty, SomeClass can define a static event
that is raised when the value of MyProperty changes. The static event
can use either of the following signatures.
public static event EventHandler MyPropertyChanged;
public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
Very good example, I used it for some general settings in application, when I want to bind some property online to components
public sealed class DataGridClass:INotifyPropertyChanged
{
private static readonly DataGridClass instance = new DataGridClass();
private DataGridClass() { }
public static DataGridClass Instance
{
get
{
return instance;
}
}
private int _DataGridFontSize {get;set;}
public int DataGridFontSize
{
get { return _DataGridFontSize; }
set { _DataGridFontSize = value;
RaisePropertyChanged("DataGridFontSize");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
Set startup properties:
DataGridClass.Instance.DataGridFontSize = 14(or read from xml)
Bind this to components properties
xmlns:static="clr-namespace:MyProject.Static"
<extgrid:ExtendedDataGrid x:Name="testGrid" ClipboardCopyMode="IncludeHeader" AutoGenerateColumns="False">
<extgrid:ExtendedDataGrid.Resources>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="FontSize"
Value="{Binding Source={x:Static static:DataGridClass.Instance},
Path=DataGridFontSize, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
</Style>
</extgrid:ExtendedDataGrid.Resources>
When you change this value somewhere in application like "Preferences"->DataGrid FontSize - to it automatically update this property for bindings with UpdateSourceTrigger
private void comboBoxFontSize_DropDownClosed(object sender, EventArgs e)
{
DataGridClass.Instance.DataGridFontSize = Convert.ToInt32(comboBoxFontSize.Text);
}
<ComboBox Grid.Column="1" Grid.Row="0" Height="21" Width="75" Name="comboBoxFontSize" HorizontalAlignment="Left"
VerticalAlignment="Center" DropDownClosed="comboBoxFontSize_DropDownClosed"
ItemsSource="{Binding Source={x:Static commands:ConstClass.ListOfFontSize},Mode=OneWay}"
SelectedItem="{Binding Source={x:Static static:DataGridClass.Instance},Path=DataGridFontSize,
Mode=OneWay,UpdateSourceTrigger=PropertyChanged}"/>
So I've spent about two hours pounding my head against the desk trying everything I can think of to bind to a property on a custom control and none of it works. If I have something like this:
<Grid Name="Form1">
<mine:SomeControl MyProp="{Binding ElementName=Form1, Path=DataContext.Enable}"/>
<Button Click="toggleEnabled_Click"/>
</Grid>
public class TestPage : Page
{
private TestForm _form;
public TestPage()
{
InitializeComponent();
_form = new TestForm();
Form1.DataContext = _form;
}
public void toggleEnabled_Click(object sender, RoutedEventArgs e)
{
_form.Enable = !_form.Enable;
}
}
TestForm looks like:
public class TestForm
{
private bool _enable;
public event PropertyChangedEventHandler PropertyChanged;
public bool Enable
{
get { return _enable; }
set { _enable = value; OnPropertyChanged("Enable"); }
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
And my control looks like:
<UserControl>
<TextBox Name="TestBox"/>
</UserControl>
public class SomeControl : UserControl
{
public static readonly DependencyProperty MyPropProperty =
DependencyProperty.Register("MyProp", typeof(bool), typeof(SomeControl));
public bool MyProp
{
get { return (bool)GetValue(MyPropProperty); }
set { SetValue(MyPropProperty, value); }
}
public SomeControl()
{
InitializeComponent();
DependencyPropertyDescriptor.FromProperty(MyPropProperty)
.AddValueChanged(this, Enable);
}
public void Enable(object sender, EventArgs e)
{
TestBox.IsEnabled = (bool)GetValue(MyPropProperty);
}
}
Absolutely nothing happens when I click the toggle button. If I put a breakpoint inside of the Enable callback it is never hit, whats the deal?
If the Enabled method does not do any more than setting the propertou you could drop it and bind the TextBox.IsEnabled directly:
<UserControl Name="control">
<TextBox IsEnabled="{Binding MyProp, ElementName=control}"/>
</UserControl>
If you want to keep such a method you should register a property changed callback via UIPropertyMetadata for the dependency property.
Also this binding is redundant:
{Binding ElementName=Form1, Path=DataContext.Enable}
The DataContext is inherited (if you don't set it in the UserControl (which you should never do!)), so you can just use:
{Binding Enable}
Further if there is trouble with any of the bindings: There are ways to debug them.