Two way Binding in WPF does not work with static members
-
01-06-2021 - |
题
Matt Hamilton told me an interesting fact about WPF: binding in two way mode with a static variable is possible in version 4.5. Unfortunately V4.5 ist still beta, I decided to change my code to get my app finally run correct.
But - still I have similar problems, here we go:
I have a very simple class 'RecallConnectionSettings'. This member of this class should be accessible from everywhere in the code, so I decided to make them static (like this):
public class RecallConnectionSettings
{
private static string Server {get;set;}
}
As you can see: there is only one variable 'Server'. Now what I want is to make 2WayMode binding from a TextBox Text-property to that 'Server' value.
So I tried this:
<UserControl....>
<UserControl.Resources>
<local:RecallConnectionSettings x:Key="recallConf"/>
</UserControl.Resources>
<TextBox Text="{Binding Source={StaticResource recallConf}, Path=Server,
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" ... Name="txtServerAdress" />
</UserControl>
This works great when I change the value in the textbox - but not from the other side. If I change the 'Server' value (by hand), the text-property in my textbox will not update.
Of course not - as I now know I have to implement INotifyProperty in my RecallConnectionSettings-class. Then it looks like this:
public class RecallConnectionSettings : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private static string s_server;
public static string Server
{
get { return s_server; }
set
{
s_server = value;
OnPropertyChanged("Server");
}
}
public static event PropertyChangedEventHandler PropertyChanged;
protected static void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}
Well - this can't work too. Because there are only static methods, I can't use the class instance to call the event:
PropertyChanged(this, new PropertyChangedEventArgs(name));
So - what to do now? I thought about using a singleton, so I did this:
public class RecallConnectionSettings : INotifyPropertyChanged
{
private static RecallConnectionSettings instance;
private RecallConnectionSettings(){}
public static RecallConnectionSettings Instance
{
get
{
if(instance == null)
{
instance = new RecallConnectionSettings();
}
return instance;
}
}
// ... here comes the other stuff
}
To make it work, I also have to prepare my UserControl, so I did this:
...
<UserControl.DataContext>
<local:RecallConnectionSettings/>
</UserControl.DataContext>
...
At this point there is no need to go on trying, because for doing this, the default constructor must be public.
No matter what I am doing: it does not work. Seems to me that I still do not understand how that works - would you be so kind and show me the trick ?
解决方案
Keep the singleton solution and replace this:
...
<UserControl>
<UserControl.DataContext>
<local:RecallConnectionSettings/>
</UserControl.DataContext>
...
</UserControl>
...
By this:
...
<UserControl DataContext="{x:Static local:RecallConnectionSettings.Instance}">
...
</UserControl>
...
其他提示
WOW - thanks Nicolas, that works !
For the other readers - here is what you have to code for the textbox now:
<TextBox Text="{Binding Path=Server, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="txtServerAdresse"/>