Binding changes unattached variable - c#

I've I really weird problem with my WPF / C# application. I've got a property which returns another property. Now I make a variable and set it to one of these properties. If I now change the value by binding, the variable is also changed.
To simplify it, here's the code:
Here's the first property:
public MainDataObject CmObj_Temp { get; set; }
Which is used here:
public MainDataObject CmObj_MainData {
get {
return TemporaryDataStore.CmObj_Temp;
}
set {
TemporaryDataStore.CmObj_Temp = value;
this.RaisePropertyChanged(() => this.CmObj_MainData);
}
}
From which I set a variable here:
CmObj_Backup = TemporaryDataStore.CmObj_Temp;
or also like this (makes no different):
CmObj_Backup = ((VM)this.DataContext).CmObj_MainData;
And also use for binding here:
<TextBox Text="{Binding CmObj_MainData.Str_Internnr, Mode=TwoWay}"/>
Now if I change the text of the Textbox it also changes it here:
CmObj_Backup.Str_Internnr);
Can someone tell my why?
How can I change that?
Thx
This is an smaller form of my code:
public class DataObject
{
public string Str_Test1 {get; set;}
public string Str_Test2 {get; set;}
// --> Much more properties
}
public static class TempData
{
public static DataObject DObj1 {get;set;}
}
public class ViewModel
{
public DataObject DObj2 {
get {
return TempData.DObj1;
}
set {
TempData.DataObjet.DObj1 = value;
this.RaisePropertyChanged(() => this.DObj2);
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
var VM = new ViewModel();
this.DataContext = VM;
}
public void SomeWhereInTheSoftware()
{
((ViewModel)this.DataContext).DObj2.Str_Test1 = "Before";
ObjBackup = ((ViewModel)this.DataContext).DObj2;
((ViewModel)this.DataContext).DObj2.Str_Test1 = "After";
// --> Here is ObjBackup.Str_Test1 also "After"!!
}
}

If you would show full code blocks instead of randomly chosen lines of code it would be easier to follow. Your example isnt very clear to me.
However, I think you are having an issue because you think you are have 2 copies of an object when you really have 1. Objects are kept as reference so if you create a MainObject and a CopyObject you cant just set CopyObject equal to MainObject and expect to have a real copy.
Again, I could be way off given I dont understand your question fully but for example:
class A {
public string Message { get; set; }
}
public static void Main()
{
A mainData = new A();
mainData.Message = "Main Data Message";
A backupData = mainData;
backupData.Message = "Backup Data Message";
Console.WriteLine(mainData.Message);
// Prints Backup Data Message
Console.WriteLine(backupData.Message);
// Prints Backup Data Message
}
Edit: cloning as a solution
As Viv mentioned in the comment the solution to your problem would be to clone the object, which creates an actual copy of the object as opposed to a reference to the object.
you would update class A in this way:
class A : ICloneable
{
public string Message { get; set; }
public override object Clone()
{
A clone = new A();
clone.Message = this.Message;
return clone;
}
}
reference to ICloneable is here http://msdn.microsoft.com/en-us/library/system.icloneable.aspx

Related

How do I change the values of variables within one class, from another?

Please excuse my ignorance for I am new to C#.
I am currently working on an MVVM project in which a viewmodel has multiple instantiated public variables that are data-bound to elements in a view (WPF). When these variables are changed they automatically update in my view. Take for instance the code segment below from my view model...
private string _displaybind;
public string DisplayBind
{
get { return _displaybind; }
set
{
SetProperty(ref _displaybind, value);
if (_displaybind.Length > 5000)
{
DisplayBind = _displaybind.Substring(_displaybind.IndexOf('\n') + 1);
}
}
}
By using the command DisplayBind = "Hello"; within my viewmodel I can push out text to a textbox I have located in my XAML view. Unfortunately, I have reached a point where I can not simply edit the value of DisplayBind.
I need to start a state machine within my viewmodel which will access several states (classes) in separate C# files. However, I have no idea how to receive, and more importantly edit the values within my viewmodel from these separate classes.
I start my state machine in my viewmodel using this...
IPMProgram ipmprogram = new IPMProgram();
ipmprogram.StartTheIPMProgram();
This is my IPMProgram class
public class IPMProgram
{
public IPMProgramState currentState = null;
public IPMProgram()
{
currentState = new BootBannerState(this);
}
public void StartTheIPMProgram()
{
while (true)
{
currentState.GetNextState();
}
}
}
This is my IPMProgramState class
public abstract class IPMProgramState
{
private IPMProgram ipmprogram;
public IPMProgram Ipmprogram
{
get { return ipmprogram; }
set { ipmprogram = value; }
}
public abstract void GetNextState();
}
And this is my BootBannerState class (The state I want to edit DisplayBind from)
class BootBannerState : IPMProgramState
{
public BootBannerState(IPMProgramState state)
:this(state.Ipmprogram)
{
}
public BootBannerState(IPMProgram ipmprograminstance)
{
this.Ipmprogram = ipmprograminstance;
}
public override void GetNextState()
{
//DisplayBind = "Hello"!
return;
}
}
Someone suggested that I should look into Dependency Injection, but I don't quite understand how it would work for me. What should I do?
Thank you for all of your help,
Tesnich

Collection of comboBoxes in WinForms

I am working on small winforms app. One of my forms contains few comboBoxes:
As I am trying to use MVP pattern in my project, so I decided to create View and Presenter for that form. The communicate via adequate interface.
ComboBox can be fully decribed (for my needs) with its DataSource (i.e. list os strings) and SelectedIndex. That' s why I created proper interface:
public interface IMyView
{
MyViewPresenter { set; }
IEnumerable<string> ComboBox1stDataSource { get; set; }
int ComboBox1SelectedIndex { get; set; }
IEnumerable<string> ComboBox2ndDataSource { get; set; }
int ComboBox2ndSelectedIndex { get; set; }
//for third comboBox it will be the same
}
I implemented that interface in my View class:
public partial class MaterialDatabasePropertiesForm : Form, IMaterialDatabasePropertiesView, IMyView
{
public MaterialDatabasePropertiesPresenter Presenter { private get; set; }
public IEnumerable<string> ComboBox1stDataSource
{
get { return comboBox1st.DataSource as List<string>; }
set { comboBox1st.DataSource = value; }
}
public int ComboBox1SelectedIndex
{
get { return comboBox1st.SelectedIndex; }
set { comboBox1st.SelectedIndex = value; }
}
public IEnumerable<string> ComboBox2ndDataSource
{
get { return comboBox2nd.DataSource as List<string>; }
set { comboBox2nd.DataSource = value; }
}
public int ComboBox2ndSelectedIndex
{
get { return comboBox2nd.SelectedIndex; }
set { comboBox2nd.SelectedIndex = value; }
}
}
When everything is set like above I use properties declared in Interface in my Presenter to change properties of comboBoxes in form.
Although it may seem like a good solution it isn' t enough for me. In my origial application I have 14 comboBoxes, and that number may change in future.
What I am trying to is making it more elastic. I was thinking about creatin some collection of comboBoxes in view, but I can' t figure it out.
My sample solutin is bad, as it doesn' t even compile:
private List<List<string>> collectionOfComboBoxesDataSources = new List<List<string>>()
{
ref comboBox1st.DataSource, // I get error:
ref comboBox2nd.DataSource, // "Cannot acces non-static field
ref comboBox3rd.DataSource // <comboBoxName> in static context"
};
//this property would be part of IMyView
public List<List<string>> CollectionOfComboBoxesDataSources
{
get { return collectionOfComboBoxesDataSources; }
set { collectionOfComboBoxesDataSources = value; }
}
What can I do to create collection (or something working similar) to acces my comboBoxes properties?
You could try to iterate through your form.
List<ComboBox> listOfCombobox = new List<ComboBox>();
foreach(var combobox in this.controls.OfType<ComboBox>())
{
listOfCombobox.Add(combobox);
}
If you're trying to do this.
Then you can access the list via index, so you can access your properties of each combobox.

Unable to Set and Get the values in C#

I am trying to use setter and getter. When i debug, the value gets set but when i try to retrieve, it gets null value.
Class1.cs
private string setMAX;
public string SETMax
{
get
{
return setMAX;
}
set
{
setMAX = value;
}
}
private string value1;
public string MaxValue
{
get
{
return value1;
}
set
{
value1= value;
}
}
Class2.cs
Class1.SETMax = Class1.value1; //This gets set
Class3.cs
//When i debug, first Class1.cs and Class2.cs completes, then it comes in Class3.cs
string max = Class1.SETMax; //I GET NULL here.
I dont know where I am wrong here.Can anyone please explain me ?
You are referencing File1 as an instance. You are probably referencing different instances. You probably want static properties.
private static string setMAX;
public static string SETMax
{
get
{
return setMAX;
}
set
{
setMAX = value;
}
}
I think you have a few things mixed up so lets start from the beginning
Class1.SETMax = Class1.value1;
// for a start you are assigning a
// private variable to a public one
// via the Class definition I'm not even sure how that compiles.
Have a look here see if this makes sense to you
// This is a Class definition
public class Class1 {
public string SETMax {get; set;}
public int MaxValue {get; set;}
}
// This is your application
public class MyApp{
// this is a private field where you will assign an instance of Class1
private Class1 class1Instance ;
public MyApp(){
//assign the instance in the constructor
class1Instance = new Class1();
}
public void Run {
// now for some fun
class1Instance.SETMax = "Hello";
Console.WriteLine(class1Instance.SETMax); // outputs "Hello"
var localInstance = new Class1();
localInstance.SETMax = class1Instance.SETMax;
Console.WriteLine(localInstance.SETMax); // outputs "Hello"
}
}

Tableadapters Not Marked as serializable?

I have 2 tables in a database and then using a datamodel in visual studio (datasets), then using 2 classes to store methods and properties of these 2 tables.
I want to store information gathered from a webform into a list but for some reason when trying to add the list to a stateview I get this error:
Type '"".""TableAdapters.""TableAdapter' in Assembly '"", Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
I have already marked the class as serializable but now the tableadapters? Here is my code:
[System.ComponentModel.DataObject]
[Serializable]
public class Example
{
int _example1 = new int();
string _example2;
string _example3;
decimal _example4 = new decimal();
public int example1
{
get { return _example1; }
set { _example1 = value; }
}
public string example2
{
get { return _example2; }
set { _example2 = value; }
}
public string example3
{
get { return _example3; }
set { _example3 = value; }
}
public decimal example4
{
get { return _example4; }
set { _example4 = value; }
}
private tblTestTableAdapter _testAdapter = null;
protected tblTestTableAdapter Adapter
{
get
{
if (_testAdapter == null)
_testAdapter = new tblTestTableAdapter();
return _testAdapter;
}
}
Webform:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
else
{
example = (List<Example>)ViewState["Examples"];
}
}
private List<Example> example;
public List<Example> GetExample()
{
return example;
}
protected void btnRow_Click(object sender, EventArgs e)
{
example = new List<Example>();
Example e = new Example();
e.example1 = Convert.ToInt32(txtE1.Text);
c.example2 = txtE2.Text;
c.example3 = txtE3.Text;
c.example4 = Convert.ToDecimal(txtE4.Text);
example.Add(e);
ViewState["Examples"] = example;
btnRow.Enabled = false;
}
What is the problem?
When marking a class as Serializable every class and dependent object class within it that is exposed externally must all be marked as Serializable. That's because whatever process that is going to perform the serialization will attempt to serialize every public element properly.
FYI, tableadapters are not meant to be exposed publicly because they expose functionality rather than properties and fields. Functionality is not transferred across the serial connection. I would recommend you remove the public nature of the adapter in your example.
Edit 2:
After rereading your code and looking for the documentation for the protection levels of serialized properties, I ran into this link that describes the real problem here. You can't serialize a readonly property (I totally forgot about this), and your tableadapter is property is readonly. Provide it with a set, and it should begin functioning.
Edit: Code sample
[Serializable]
public class MySerializableClass
{
public MySerializableClass()
{
}
// This string serializes ok
public string MyStringProperty { get; set; }
// Because this property is public in scope it must be serializable
// because it will be translated at a public scope. This will throw
// an exception
public myNonSerializableClass NotSerializableObject { get; set; }
// Because this property is private in scope, it will not be included
// in any serialization calls, so it will not throw an exception, but
// it will also not be available in whatever remote class calls it.
private myNonSerializableClass SerializableObject { get; set; }
// Because this property object is serializable in code it will be
// ok to make it public because it will natively serialize itself
public MyOtherSerializableClass OtherSerializableObject { get; set; }
}

Why is it allowed to set a property that doesn't set anything in C#?

I've been reviewing the PRISM toolkit and I find many examples where they declare a public property with empty getters/setters yet they can still set the property of the instantiated class. How/why is this possible?
public class ShellPresenter
{
public ShellPresenter(IShellView view)
{
View = view;
}
public IShellView View { get; private set; }
}
//calling code
ShellPresenter sp = new ShellPresenter();
//Why is this allowed?
sp.View = someView;
This is a new feature in C# 3.0.
http://msdn.microsoft.com/en-us/library/bb384054.aspx
In C# 3.0 and later, auto-implemented properties make property-declaration more concise when no additional logic is required in the property accessors.
They're using C# auto properties. It's a convenience whereby the compiler generates the backing field for you. private set means that the property is read-only from outside the class. So, if sp.View = someView; is being used outside of the class then it will result in a compiler error.
Decompiling your ShellPresenter with the Red Gate .NET Reflector
public class ShellPresenter
{
// Fields
[CompilerGenerated]
private IShellView <View>k__BackingField;
// Methods
public ShellPresenter(IShellView view)
{
this.View = view;
}
// Properties
public IShellView View
{
[CompilerGenerated]
get
{
return this.<View>k__BackingField;
}
[CompilerGenerated]
private set
{
this.<View>k__BackingField = value;
}
}
}
What you posted is not allowed unless the object is being set within the class itself. Here's a code sample of what is and is not allowed.
public interface IShellView
{
}
public class View:IShellView
{
}
//public class SomeOtherClass
//{
// static void Main()
// {
// IShellView someView = new View();
// //calling code
// ShellPresenter sp = new ShellPresenter();
// //Why is this allowed?
// sp.View = someView;//setting a private set outside the ShellPresenter class is NOT allowed.
// }
//}
public class ShellPresenter
{
public ShellPresenter()
{
}
public ShellPresenter(IShellView view)
{
View = view;
}
static void Main()
{
IShellView someView = new View();
//calling code
ShellPresenter sp = new ShellPresenter();
//Why is this allowed?
sp.View = someView;//because now its within the class
}
public IShellView View { get; private set; }
}
C# compiler generates backend field for you. This syntax was introduced for anonymous types support (like new { A = 1, B = "foo" } )

Categories