Bind Textbox Text to a Static Property - wpf

I have a Static Class with the following Static Property:
public static class PrintingMethods
{
public static String DocsCountString
{
get
{
return printDocuments.Count.ToString();
}
}}
I have a text box that I bind to this property:
<TextBlock Text="{x:Static my:PrintingMethods.DocsCountString}" x:Name="PagesNumber"/>
This works - I can see the number in the Text, But it never changes If the Property Value Change.
I am quite new to this, I know there are things like Dependency Object and INotify Interface but this won't work for Static.
If anyone can help me with a working code (modification to what I wrote) to Achieve real time textChange that would be great, Thanks!!!

Answer on our comments:
If you use the Singleton Pattern, you can bind to it like that
public sealed class MySingleton : INotifyPropertyChanged
{
public void RaiseProperty(string aPropName)
{
// implementation of INotifyPropertyChanged
}
public static MySingleton Instance
{
get{ return sInstance; }
}
public string MyProperty
{
get {return mMyProperty;}
set {mMyProperty = value; RaiseProperty("MyProperty"); }
}
private string mMyProperty;
private static MySingleton sInstance = new MySingleton();
}
As you can see you can easily use the INotifyPropertyChanged interface and implementation with a singleton class. You might want to make the constructor private to disallow creating another instance of this class. Also it would be possible to lazy allocate the MySingleton instance. You will find much more about singletons on stackoverflow.
<TextBlock Text="{Binding Source={x:Static my:MySingleton.Instance}, Path=MyProperty}"/>
The important part here now is the Binding and the overriden Source. Usually Binding takes the current DataContext. By setting a new Source the DataContext is irrelevant and the new Source is used to get the value behind the Path property.

you should use function in modifier is internal like:
Form2:
internal string foo()
{
return nom;
}
Form1:
form2 win= new form2();
win.ShowDialog();
Textbox.Text = win.foo();

Related

Static Property Bind to Grid in wpf

I have a lot of static poperties in my class library. I want to bind the property values in grid with two way binding. How can bind it?
public class AllStaticProperty
{
public static int JA{get;set;}
public static float JB{get;set;}
public static bool JC{get;set;}
public static int[] JD=new int[1000];
//More properties here
public static float[] ZZ=new float[2000];
}
I want bind static property name grid first column field and user enter the property value in grid second column then back to store the value in static property. how can I bind( I have more than 3000 static property)
If you want to bind properties and reflect changes to them in the user interface, you have to implement INotifyPropertyChanged in the corresponding class and raise the PropertyChanged event whenever a property changes its value to trigger binding updates in controls to get the latest value.
However, static properties cannot access instance methods, so how should they raise property changed notifications? There are ways to achieve this, as you can see in this related post, but it is bad design. Another issue here is to bind a static property of a non-static class two-ways, but there are also workarounds.
I recommend to overthink your design and create view models that implement INotifyPropertyChanged, e.g.:
public class SampleViewModel : INotifyPropertyChanged
{
private int _ja;
public int JA
{
get => _ja;
set
{
if (_ja == value)
return;
_ja = value;
OnPropertyChanged();
}
}
// ...other properties and backing fields.
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Then you can bind a property with the usual syntax and add Mode=TwoWay if that is not the default already.
SomeProperty="{Binding JA, Mode=TwoWay}"
An alternative option is to create one or more wrapper view models that are implemented as above, but access the static properties of your AllStaticProperty class, but then you need to synchronize the view model with the static properties, too, if any static property changes.

WPF C# INotifyPropertyChanged doesn't fire up

I am building a WPF application that as part of its flow, checks for network connectivity and display the IP address in a TextBlock.
Now I am trying to update the TextBlock Text property everytime the IP address changes for whatever reason.
I have the IP address change working fine, but i could not get INotifyPropertyChanged to work.
I read all the possible solutions and implementations but I couldn't come up with a working code.
The public property gets the value from a static string from the Network Helper class.
So, the code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
public string ipAddress
{
get { return NetworkStatus.localIP; }
set
{
if (value != NetworkStatus.localIP)
{
NetworkStatus.localIP = value;
NotifyIPChanged("IpAddress");
}
}
}
private void NotifyIPChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
XAML:
<TextBlock x:Name="ipTxt"
TextWrapping="Wrap"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Text="{Binding DataContext.ipAddress}"
Height="30"
Width="110"
Margin="-30,10,0,-10"
/>
UPDATE
NetWorkStatus.cs -- static bool IsNetworkAvailable()
...
if (statistics.BytesReceived > 0 || statistics.BytesSent > 0)
{
IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
localIP = host.AddressList.FirstOrDefault(ip => ip.AddressFamily == AddressFamily.InterNetwork).ToString();
return true;
}
As you can see this method sets a static string "localIP". This is then evaluated by IpAddress property.
Why the TextBlock Text property doesn't get updated when the IP Address changes?
Rename the property to IpAddress so that it adheres to widely accepted naming conventions.
public string IpAddress
{
get { return NetworkStatus.localIP; }
set
{
if (value != NetworkStatus.localIP)
{
NetworkStatus.localIP = value;
NotifyPropertyChanged();
}
}
Use the CallerMemberName attribute on the propertyName parameter of your notification method, so that you do not have to write the name explicitly.
using System.Runtime.CompilerServices;
...
private void NotifyPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Bind it correctly. The current DataContext is already used as source object of the Binding. You must not add it to the property path.
<TextBlock Text="{Binding IpAddress}" ... />
In a possible next step you might want to separate the view from the view model and put the property in a separate class:
public class ViewModel : INotifyPropertyChanged
{
public string IpAddress
{
get ...
set ...
}
...
}
and assign the Window's DataContext to an instance of the view model class:
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
I think you need to take a closer look to how WPF works.
As a remark, there is no need to implement INotifyPropertyChanged in code behind. If you are using events, then you can automatically refresh the properties of the targeted UI element.
However, using code behind is not a good practice in our days. You should take a look at MVVM pattern. You have there a Model, View and ViewModel. The ViewModel should implement INotifyPropertyChanged.
The fact is that your code is in my opinion absolutely wrong. The naming is not fine : when you implement INotifyPropertyChanged you should not implement it only for a property, and the name should not look like : NotifyIPChanged, instead you should use RaisePropertyChanged, NotifyPropertyChanged or OnPropertyChanged. In setters you should not refresh something else, but only the property that you are targeting, because otherwise the Single Responsability principle is violated, as in your case. Also a bad practice is to bind to Code Behind.
I hope this post would make you to read more about MVVM and WPF. Good luck!
is it possible that the Event doesnt react, because the first letter of IpAdress is an Upper?
NotifyIPChanged("IpAddress");
public string ipAddress
Text="{Binding DataContext.ipAddress}"

Using callback interface as a DependencyProperty in WPF?

I apologize for the lengthy question, but I feel like it is necessary to include all of this information.
Until now, I've been using a possibly-unorthodox way of adding UserControls to my applications. Let's say I have a UserControl called Diagnostics that has a button, that when clicked, performs a function that is specific to the application that owns it. For example, if I drop Diagnostics into AppA, I want it to display "A", and if I drop it into AppB, I want AppB to define the behavior so it displays "B".
I typically implement this via a callback interface that is passed to the UserControl's constructor, which is pretty straightforward. Here's some sample "code" that probably won't compile, but is presented just to clarify what I've basically done before, and what I am trying to do:
public interface IDiagnosticsCallback {
void DisplayDiagnostics(); // implemented by owner of Diagnostics UserControl
}
public class MyApp : IDiagnosticsCallback {
public void DisplayDiagnostics() {
MessageBox.Show("Diagnostics displayed specifically for MyApp here");
}
}
public Diagnostics : UserControl {
private IDiagnosticsCallback _callback { get; private set; }
public Diagnostics(IDiagnosticsCallback callback) {
_callback = callback;
}
public void ShowDiagnostics_Click(object sender, EventArgs e) {
_callback.DisplayDiagnostics();
}
}
The problem I had in the past was understanding how to declare a UserControl that takes a parameter in its constructor (i.e. doesn't have a default constructor) in XAML, and apparently you can't. I worked around this with a fairly-inelegant method -- I would give the main panel a name in XAML, and then from code-behind I would create Diagnostics, passing it the necessary callback, and then I would add Diagnostics to the panel's list of children. Gross and violates usage of MVVM, but it works.
This weekend, I decided to try to learn how to do it for a class and a TextBox, and it turns out that all I had to do was to create a DependencyProperty in my UserControl and use databinding. It looks something like this:
public ClassA
{
public void ShowSomethingSpecial()
{
MessageBox.Show("Watch me dance!");
}
}
public MyApp
{
public ClassA Foo { get; set; }
}
public Diagnostics : UserControl
{
public static readonly DependencyProperty SomethingProperty = DependencyProperty.Register("Something", typeof(ClassA), typeof(Diagnostics), new PropertyMetadata());
public ClassA Something
{
get { return (MyApp)GetValue(SomethingProperty); }
set { SetValue(SomethingProperty, value); }
}
// now uses default constructor
public void ShowSomethingSpecial_Click(object sender, EventArgs e)
{
Something.ShowSomethingSpecial();
}
}
MyApp.xaml
<diags:Diagnostics Something="{Binding Foo}" />
So Foo is a property of MyApp, which is databound to the Something DependencyProperty of Diagnostics. When I click the button in the UserControl, the behavior is defined by ClassA. Much better, and works with MVVM!
What I'd like to do now is to go one step further and instead pass a callback interface to my UserControl so that it can get the states of my digital inputs and outputs. I'm looking for something like this:
public Diagnostics : UserControl
{
public interface IDioCallback
{
short ReadInputs();
short ReadOutputs();
void SetOutput( char bit);
}
public IDioCallback DioCallbackInterface {
get { return (IDioCallback)GetValue(DioCallbackInterfaceProperty); }
set { SetValue(DioCallbackInterfaceProperty,value); }
}
// Using a DependencyProperty as the backing store for DioCallbackInterface. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DioCallbackInterfaceProperty = DependencyProperty.Register("DioCallbackInterface",typeof(IDioCallback),typeof(Diagnostics),new PropertyMetadata(0)); // PropertyMetadata is the problem...
}
public class DIO : IDioCallback
{
public short ReadInputs() { return 0; }
public short ReadOutputs() { return 0; }
public void SetOutput( char bit) {}
}
public class MyApp
{
public DIO MyDIO { get; set; }
}
MyApp.xaml
<diags:Diagnostics DioCallbackInterface="{Binding MyDIO}" />
While my code (maybe not the exact code above, but my real project) does compile successfully, it appears that the PropertyMetadata passed to Register is at fault. I get an exception that says "Default value type does not match type of property 'DioCallbackInterface'."
Am I doing something really unorthodox, or is this approach to databinding interfaces actually possible? If not, what are the recommended ways of defining how a UserControl behaves based on the application it's being used in?
The exception you have mentioned because of this:
new PropertyMetadata(0)
You have passed 0 (of type Int32) instead of the null or whatever you like for your interface: IDioCallback.
I cannot say that the way you select is wrong, but you should keep in mind that every user of your UserControl must implement that interface you have defined. If you have several properties that you would like to pass to the UserControl, you can basically discard them via DependencyProperty.
In your case you also would like to inject some logic to the UserControl Button. Let me suppose that this control has only one button. MVVM-way to handle Button.Click event is done via ICommand - you can declare the command property in your ViewModel and use it as data source for data binding in your UserControl as DependencyProperty, passing it properly to the Button.
Also you can have an agreement with all of your data context, and use special name for that property. For example:
public interface IViewModelWithCommand
{
public ICommand TheCommand { get; }
}
Implement it for each data context you need, and use TheCommand property name inside your data template of your UserControl. In the code-behind you can create type validation of DataContext passed to your UserControl, and throw an exception in case the type is not implements your interface
Here several articles you probably should be interested in:
RelayCommand
Commands, RelayCommands and EventToCommand
How to use RelayCommands
Using RelayCommand will simplify your life because you don't need to re-implement interface for every command, instead, you need to pass valid action that you want.

Binding to observable collection, dependency property fails

I have a usercontrol where I need a list of a simple class I've made, called Person:
public class Person {
public string Name { get; set; }
}
Now in the usercontrol, I need to have a ObservableCollection<Person> that I can bind to. So I figure I need to make it a dependency property. So in the usercontrol I have the following:
public static readonly DependencyProperty PersonsDependencyProperty =
DependencyProperty.Register("Persons", typeof(ObservableCollection<Person>),
typeof(PersonUserControl));
And the property is like this:
public ObservableCollection<Person> Persons
{
get
{
return (ObservableCollection<Person>)GetValue(PersonsDependencyProperty);
}
set
{
SetValue(PersonsDependencyProperty, value);
}
}
Now in my MainWindow.xaml codebehind I make an ObservableCollection<Person> called PersonList, set the mainwindow datacontext to self, and bind to it like so:
<Local:PersonUserControl Persons="{Binding PersonList}">
</Local:PersonUserControl>
And I get the error: Exception has been thrown by the target of an invocation. - No further explanation. Can anybody tell me how to react to it or what I'm doing wrong.
I hope I'm being clear enough.
PersonsDependencyProperty should be just PersonsProperty. Hard to say whether that's the underlying cause without more information, but that's certainly a problem. WPF appends "Property" onto the binding path in order to find the related dependency property. Thus, it won't find yours.

Using dependency properties in wpf

I'm not quite sure if I've got the right grasp on this or not, what I've read seems to agree with what I'm trying to do, however It doesn't seem to be working.
If I add an additional owner to a dependency property of a class, whenever the orig class dp changes, the change should get propagated to the additional owner, correct?
What I have is a custom control, which I want to set a property on, and then on certain objects that are within the custom control data template inherit this property value.
public class Class1: DependencyObject{
public static readonly DependencyProperty LongDayHeadersProperty;
public bool LongDayHeaders {
get { return (bool)GetValue(LongDayHeadersProperty); }
set { SetValue(LongDayHeadersProperty, value); }
}
static Class1(){
LongDayHeadersProperty = DependencyProperty.Register("LongDayHeaders", typeof(bool), typeof(Class1),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
}
}
public class Class2: DependecyObject{
public static readonly DependencyProperty LongDayHeadersProperty;
public bool LongDayHeaders{
get{ return(bool)GetValue(LongDayHeadersProperty); }
set{ SetValue(LongDayHeadersProperty, value); }
}
static Class2(){
LongDayHeadersProperty = Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));
}
}
But if I assign a DependencyPropertyDescriptor to both properties, it only fires for the Class1 and Class2 doesn't change.
Have I missed something in my understanding?
UPDATE
After some testing, I'm not even sure if my child control is considered a child control within the logical or visual tree. I think it is, but the lack of success leads me to believe otherwise.
There a many class2's which exist in an observable collection of class1. This, to me, makes them childs of class1? But even if I use RegisterAttach on class2, and set the property in class1, it doesn't seem to have any effect?
As MSDN states, the Inherits flag only works when you use RegisterAttached to create the property. You can still use the property syntax for the property.
Update
For clarity, here is how I would define the properties:
public class Class1 : FrameworkElement
{
public static readonly DependencyProperty LongDayHeadersProperty =
DependencyProperty.RegisterAttached("LongDayHeaders",
typeof(bool),
typeof(Class1),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits));
public bool LongDayHeaders
{
get { return (bool)GetValue(LongDayHeadersProperty); }
set { SetValue(LongDayHeadersProperty, value); }
}
}
public class Class2: FrameworkElement
{
public static readonly DependencyProperty LongDayHeadersProperty =
Class1.LongDayHeadersProperty.AddOwner(typeof(Class2));
public bool LongDayHeaders
{
get{ return(bool)GetValue(LongDayHeadersProperty); }
set{ SetValue(LongDayHeadersProperty, value); }
}
}
If you want your children to be logical children of your control, you need to call the AddLogicalChild. Also, you should expose them through the LogicalChildren property. I must also point out that both classes must derive from FrameworkElement or FrameworkContentElement, as the logical tree is only defined for these elements.
Since you are using an ObservableCollection, you would handle the collection changed events and Add/Remove the children depending on the change. Also, the LogicalChildren property can just return your collection's enumerator.
You are confusing DependencyProperties with Attached (Dependency) Properties.
A DP is for when a class wants bindable, stylable etc properties on itself. Just like .NET properties, they are scoped within their classes. You can register for a property changed event on individual objects, but not globally. TextBox.Text is an example of this. Note that Label.Text is unrelated to TextBox.Text.
An AP is for when a class wants to decorate another object with additional properties. The class that declares the AP is able to listen for property changed events on ALL instances of other objects that have this AP set. Canvas.Left is an example of this. Note that you always have to qualify this setter: <Label Text="Hi" Canvas.Left="50"/>

Resources