I am fairly new to C# so be gentle.
My end goal is to have a few different types of classes for inheritance (example below: Level). These inherited classes do two things, have .Value property with different setters depending on the class, and a .Action method, unique for every instance so it is an override.
Question: how do i set the .Value property from a method on the class. This is the line of code (line 27) that does not work from the example below. And I don't understand why.
Potentiometer.Value = Convert.ToDouble(data);
// Code taken from https://dotnetfiddle.net/YNJpjf
using System;
namespace Main {
class Program
{
static Device device = new Device();
static void Main(string[] args)
{
device.HandleDataUpdate("50");
}
}
public class Device
{
public class Potentiometer : Level
{
public override void Action()
{
Console.WriteLine("value is at: {0}", this.Value);
}
}
public void HandleDataUpdate(String data)
{
Potentiometer.Value = Convert.ToDouble(data);
}
}
public class Level
{
private Double thisValue;
public Double Value
{
get => thisValue;
set
{
if (thisValue != value)
{
thisValue = value;
Action();
}
}
}
public virtual void Action()
{
}
}
}
Give Level a protected abstract method OnSetValue, forcing each subclass to override it. Now the setter of Value can call OnSetValue before the value is set:
public class Level {
private double val;
public double Value {
get {
return val;
}
set {
OnSetValue(value);
val = value;
}
}
protected abstract void OnSetValue(double val);
...
}
public class Potentiometer : Level {
protected void OnSetValue(double val) {
...
}
}
You need to create an instance of Potentiometer.
https://dotnetfiddle.net/8JQDyO
You're trying to set value of class field, which is impossible, not of object's field. You have to make instance of Potentiometer inside the Device, if you want to do this , you could make method or change code logic.
Related
So, I have a statusbar as UserControl.
Model:
public class StatusBarModel : BindableBase
{
private string _status;
public string Status
{
get { return _status; }
set
{
_status = value;
RaisePropertyChanged("Status");
}
}
private int _p_value;
public int P_Value
{
get { return _p_value; }
set
{
_p_value = value;
RaisePropertyChanged("P_Value");
}
}
}
ViewModel:
public class StatusBarVM : BindableBase
{
readonly source.elements.StatusBar.StatusBarModel _model = new source.elements.StatusBar.StatusBarModel();
public StatusBarVM()
{
_model.PropertyChanged += (s, e) => { RaisePropertyChanged(e.PropertyName); };
}
public string Status
{
get { return _model.Status; }
set { _model.Status = value; }
}
public int P_Value
{
get { return _model.P_Value; }
set { _model.P_Value = value; }
}
}
And for example I wanna change Status variable from others ViewModels.
How I can do it? I have seen examples with only buttons and etc.
There are multiple ways to achieve your requirement. as #bitclicker says, you can use static class that hold its value. But I think It is too much that makes it static class, because that variable value may be used only two viewmodel.
I suggest you communicate between two view model. you will find Prism's event aggregator or you could implement your own event publish-subscriber model. making your own event pub-sub model would help you to make a first step into the design pattern.
You could create a static class to hold that value.
public static class Globals()
{
public static StatusBarModel GlobalStatus { get; set; }
}
Then whenever you want to alter it you just do
Globals.GlobalStatus.Status = "something";
Globals.GlobalStatus.P_Value = 14;
does that accomplish what you need?
I'm currently programming an app for windows phone 8.1. I've some page classes and one normal C# class in this project.
On the page I'm currently working on are some texboxes, comboboxes and one button.
I want to enable the button, whene the user has given input to all text- and comboboxes. So I set a variable in the C# class Variables.cs whene e.g. he entered a number which I can parse to double and selected an item in a combobox. Variables.cs looks like this:
class Variables
{
public static int iSelectedIndex = -1;
private static void SupplyParameterReady()
{
if (tbSupply1 && tbSupply2 && unitSupply1 && unitSupply2)
{
SupplyParameter.ParameterCompleted(true);
}
else
{
SupplyParameter.ParameterCompleted(false);
}
}
public static bool tbSupply1
{
get
{
return tbSupply1;
}
set
{
tbSupply1 = value;
if (value)
SupplyParameterReady();
}
}
}
Every time a variable is set true the method SupplyParameterReady() checks if all the other variables are true too.
If this is the case I want to call the method ParameterCompleted(bool) in my page class, looks like this:
public sealed partial class SupplyParameter : Page
{
...
public void ParameterCompleted(bool ready)
{
btnSupplyCalculationGo.IsEnabled = ready;
}
}
This brings the issue that ParameterCompleted(bool) isn't static. So I need to have an instance of the class SupplyParameter.
But don't want to create a new instance of it, because that brings an infinite loop between the 2 classes.
I guess there has to be already an instance, which is created when the page is loaded. But where is this instance? Or how can I call this method without an instance?
If you move things around, you could have a (non static) Variables member inside your SupplyParameter Page and pass this to the constructor. It would look like this
class Variables
{
public int iSelectedIndex = -1;
public SupplyParameter _page;
public Variables(SupplyParameter page)
{
_page = page;
}
private void SupplyParameterReady()
{
if (tbSupply1 && tbSupply2 && unitSupply1 && unitSupply2)
{
_page.ParameterCompleted(true);
}
else
{
_page.ParameterCompleted(false);
}
}
public bool tbSupply1
{
get
{
return tbSupply1;
}
set
{
tbSupply1 = value;
if (value)
SupplyParameterReady();
}
}
}
public sealed partial class SupplyParameter : Page
{
Variables _vars;
public SupplyParameter()
{
vars = new Variables(this);
}
...
public void ParameterCompleted(bool ready)
{
btnSupplyCalculationGo.IsEnabled = ready;
}
}
I have Class B that derives from Class A.
How can I override parts of Draw method in Class A and keep parts of it and throw away the rest?
For example here I want the Draw method in Class B to DrawRectangles() and instead of DrawrCircles to DrawTriangles.
public class A
{
public virtual void Draw()
{
DrawRectangles();
DrawCircles();
}
}
public class B : A
{
public override void Draw()
{
// I want to still draw rectangles
// but I do not want to draw circles
// I want to draw triangles instead
}
}
Then why don't you just call the methods you want to execute ?
public override void Draw()
{
DrawRectangles();
DrawTriangles();
}
There is no partially overriding for methods.You can declare partial methods but they are not the same.If you want to override, you need to overrride whole method.
I would suggest you to go with the below:
public class A
{
public virtual void OverridableDraw()
{
DrawCircles(); // declare all those which can be overrided here
}
public void Draw()
{
DrawRectangles(); // declare methods, which will not change
}
}
public class B : A
{
public override void OverridableDraw()
{
// just override here
}
}
The Idea is to override only those, which tends to change.
Then, you can call both the methods.
OverridableDraw();
Draw();
As an alternative design, if you have lots of different 'parts' you have to draw, and have not so much alternate drawing, I'd personally use a [Flag] enumeration
[Flags]
public enum DrawParts
{
Rectangles = 1,
Circles = 2,
Triangles = 4,
//etc
}
public class A
{
//or a regular get/setter instead of a virtual property
public virtual DrawParts DrawMode { get { return DrawParts.Rectangles | DrawParts.Circles; } }
public void Draw()
{
var mode = DrawMode;
if (mode.HasFlag(DrawParts.Circles))
DrawCircles();
if (mode.HasFlag(DrawParts.Rectangles)) //NB, not elseif
DrawRectangles();
//etc
}
}
public class B : A
{
public override DrawParts DrawMode{get{return DrawParts.Rectangles | DrawParts.Triangles; }}
}
I have a class called Global.cs:
public class Global
{
private string id= string.Empty;
public string Id
{
get { return id;}
set { id= value; }
}
}
Now in the Main class,
public class Main
{
public Global objGlobal;
protected void Page_Load(object sender, EventArgs e)
{
objGlobal= new Global();
objGlobal.id="XX001";
}
public void Setdata()
{
// Trying to access objGlobal.id value here but it's null
}
}
What am I missing?
Shouldn't you always be getting/setting "Id" rather than "id". As "id" is private.
Well, your XX class instance is more than one time.
If you need to persist some user-retalive info, try storing it into the SessionState.
If you need to just have the static class with some static data, add the static keyword to both class and its members.
I have made a Base Form which is inherited by most Forms in the application. Base form contains a Status Bar Control that displays user name which is internally a static string. User can Switch User at any point in the application by pressing a button on status bar. At this point the user name in the status bar should also change, as if now it only changes in code and UI has no idea about the change. I have googled around and found that i need to bind the label with that static string by implementing a INotifyProperty Interface. I have implemented many example code without success.
Appreciate any help
use BindableAttribute for the property you want to bind a control to it.
[Bindable(true)]
public int Username {
get {
// Insert code here.
return 0;
}
set {
// Insert code here.
}
}
You must implement a class to notify prop changed and therefore the prop can not be static. Combine with a singleton pattern and you have yout solution.
public class Global : INotifyPropertyChanged
{
private string _userName;
public string UserName
{
get
{
return this._userName;
}
set
{
if (this._userName == value)
{
return;
}
this._userName = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("UserName"));
}
{
}
public event PropertyChangedEventHandler PropertyChanged;
private Global() {}
public static readonly Global Get = new Global();
}
Usage:
var currUserName = Global.Get.UserName;
Global.Get.PropertyChanged += (s, e) => Console.WriteLine(e.PropertyName);
Global.Get.UserName = "John";
And bind to Global.Get to property UserName.
I would:
1- Add a timer to the base form to update the status bar. (the timer resolution is uo to your requirement).
the timer Tick handler would be something like this:
private void timerStatusUpdate_Tick(object sender, EventArgs e)
{
toolStripStatusLabelMessage.Text = StatusMessage();
}
2 - Add a virtual StatusMessage method to your base class:
class BaseForm : Form
{
.......
public virtual string StatusMessage()
{
return "override me!";
}
}
3- override StatusMessage in all your derived classes
class XXXForm : BaseForm
{
........
public override string StatusMessage()
{
return "XXXForm status message";
}
}
I use Reactive Extensions for these things
For example if you have a Context class with a property UserName
you could do this
public static class Context
{
public static Subject<string> UserChanged = new Subject<string>();
private static string user;
public static string User
{
get { return user; }
set
{
if (user != value)
{
user = value;
UserChanged.OnNext(user);
}
}
}
}
And then on your forms just do
Context.UserChanged.ObserveOn(SynchronizationContext.Current)
.Subscribe(user => label.Text = user);
The ObserveOn(SynchronizationContext.Current) makes it safe for cross thread operation calls