I've defined a class with the following property:
private ObservableCollection<Job> allJobs;
Access is defined as follows:
public ObservableCollection<Job> AllJobs
{
get
{
return this.allJobs;
}
set
{
this.allJobs = value;
}
}
The get set works fine when I assign a whole ObservableCollection to the property, the set works fine for retrieving it obviously. But why have I lost all the methods that normally allow me to 'Add' (i.e. add 1 job to the collection)?
At the moment I'm having to create a temporary collection to populate to then assign to the allJobs property and I shouldn't have to.
Any ideas??
What do you mean with 'lost methods'? Have you tried AllJobs.Add()? The following code works for me:
void Main()
{
AllJobs = new ObservableCollection<Job>();
AllJobs.Add(new Job());
}
public class Job { }
private ObservableCollection<Job> allJobs;
public ObservableCollection<Job> AllJobs
{
get
{
return this.allJobs;
}
set
{
this.allJobs = value;
}
}
EDIT:
Based on your comment I've amended my code as follows but everything still works for me, I have noticed however that you don't seen to initialise the allJobs collection anywhere.
void Main()
{
PresentationManager.Instance.AllJobs.Add(new Job());
}
public class Job { }
sealed class PresentationManager
{
public static readonly PresentationManager Instance = new PresentationManager();
private PresentationManager()
{
allJobs = new ObservableCollection<Job>();
}
private ObservableCollection<Job> allJobs;
public ObservableCollection<Job> AllJobs
{
get { return this.allJobs; }
set { this.allJobs = value; }
}
}
Normally you wouldn't want a setter for such a property, as you would lose all events bound to the ObservableCollection when the setter is used.
public ObservableCollection<Job> AllJobs { get; private set; }
Related
My model is mainly made from the 2 classes below (I actually got another class which inherits from the abstract class but it doesnt matter I think):
public abstract class FeedForEvents: BaseObservableObject
{
public abstract void ReadFeed();
public List<Event> Events { get; set; }
public void AddEvent(Event aEvent)
{
Events.Add(aEvent);
OnPropertyChanged("Events");
}
}
public class Event : BaseObservableObject
{
public string MyProp
{
get
{
return _myProp;
}
set
{
_myprop= value;
OnPropertyChanged();
}
}
}
My form contains:
private BindingList<FeedForEvents> ListFeedsForEvents = new BindingList<FeedForEvents>();
private BindingList<Event> ListEvents
=> new BindingList<Event>(ListFeedsForEvents.SelectMany(m =>m.Events).ToList());
private BindingSource pagesBindingSource = new BindingSource();
public void RefreshGrid()
{
pagesBindingSource.DataSource = ListEvents;
this.grdEvents.DataSource = pagesBindingSource;
this.grdEvents.AutoGenerateColumns = true;
}
But even if my 2 objects correctly raised the PropertyChanged notficiation, the interface never show the objects updated (unless I manually refresh them by pressing a button to manually call RefreshGrid() ). Why?
I'm sure this has been asked before I just don't know the correct way to word it so I can't find what I am looking for.
I have a class with a field which I want to be able to see from the outside, just not be able to modify it directly..
public class myclass
{
public int value;
public void add1()
{
value = value + 1;
}
}
So I would really like to only have the 'value' field modifiable from the method add1() but I still want to be able to see the value of 'value'.
EDIT: I was thinking only modifiable via the class myclass, but I typed otherwise. Thanks for pointing that out.
public int value { get; private set; }
You cannot make it modifiable only by the method add1, but you can make it only modifiable by myclass.
See this:
https://msdn.microsoft.com/en-us/library/75e8y5dd.aspx
Please consider the following options to encapsulate a field (i.e. provide an "interface" for the private field value):
Provide the public method (accessor):
// ...
private value;
// ...
public void Add()
{
++value;
}
public int GetValue()
{
return value;
}
Provide the public property (only accessor):
// ...
private value;
// ...
public void Add()
{
++value;
}
public int Value
{
get { return value; }
}
Provide the auto-implemented property (public accessor, private mutator):
// ...
// The field itself is not needed: private value;
// ...
public void Add()
{
++Value;
}
public int Value { get; private set; }
It is worth noting that some IDEs or IDE–plugins provide the appropriate refactoring called "Encapsulate Field".
You can use public property without setter to just see the value from outside. make the value private so its only visible inside the calss.
public class myclass
{
private int value;
public void add1()
{
value = value + 1;
}
public int Value
{
get
{
return value;
}
}
}
I'm writing a wrapper for OPC communication to a controller, and I have created a component like follows;
public class OPCGroup : Component
{
(snipped)
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<OPCItem> Items
{
get { return mItems; }
set { mItems = value; }
}
}
Each item in the Items list above looks like this
public class OPCItem : MarshalByRefObject, IDisposable
{
private String mName;
private String mTag;
private object mValue;
public String Name
{
get { return mName; }
set { mName = value; }
}
public String Tag
{
get { return mTag; }
set { mTag = value; }
}
public object Value
{
get { return mValue; }
set { Change(value, true); }
}
public event OPCItemEvent Changed;
}
Now the problem is that the Changed event of the OPCItem is not changeable in design time, i can add events to the items in run time using
opcGroup1.Items[0].Changed += new OPCItemEvent(Item0Changed);
However, i would like to be able to bind the events in design time instead as it is easier.
I have tried creating the events manually using the IEventBindingService in a custom UITypeEditor as follows
IEventBindingService eventBindingService = provider.GetService(typeof(IEventBindingService)) as IEventBindingService;
EventDescriptorCollection edc = TypeDescriptor.GetEvents(Group.Items[0]);
EventDescriptor Event = edc.Find("Changed", false);
PropertyDescriptor pd = eventBindingService.GetEventProperty(Event);
pd.SetValue(Group.Items[0], Group.Items[0].Name + "Changed");
But then I get the error
Events cannot be set on the object passed to the event binding service because a site associated with the object could not be located
So then i implemented the IComponent interface in the OPCItem class to get the Site property, but now the collection items are shown on the designer.
Any advice on how to approach this problem?
I have to bind my GUI to the interface:
public interface IMain
{
public CTopObject MyObject { get; }
public CInsideObject MidObj { get; }
public CInsideObject MyCollectionObject { get; }
}
Objects definitions:
public class CMain
{
public CTopObject MyObject { get { return this.myObject; }
public CInsideObject MidObj { get { return this.MyObject.SomeObject; } }
public CInsideObject MyCollectionObject
{ get
{
if(this.MyObject.Thedict.Contains(0))
return this.MyObject.TheDict[0];
else
return default(CInsideObject);
}
} //0 is ofcourse an example
}
public class CTopObject
{
private string someString;
public string SomeString
{
get { return this.someString; }
set
{
this.someString = value;
if(this.PropertyChanged!=null) this.PropertyChanged(this, "SomeString");
}
}
private ObservableDictionary int, CInsideObject> theDict; //how to open bracket on stackoverflow? ;)
public ObservableDictionary int, CInsideObject> TheDict
{
get { return this.theDict; }
}
private CInsideObject someObject;
public CInsideObject SomeObject
{
get { return this.someObject; }
}
//There is constructor. After that, there is init method,
//that creates new thread. The thread updates SomeString,
//representing object state. After thread raise specified event
//callback method begin to initialize SomeObject and
//after callback from SomeObject it adds some objects to
//TheDict, and initialize them.
}
public class CInsideObject : INotifyPropertyChanged
{
private string someString;
public string SomeString
{
get { return this.someString; }
set
{
this.someString = value;
if(this.PropertyChanged!=null) this.PropertyChanged(this, "SomeString");
}
}
//There is constructor, and init method that creates new thread.
//This thread updates SomeString that represents actual state of object.
}
Now in my application main.xaml.cs file, I have field
private IMain theMain;
Then I set DataContext of my window to IMain field:
theMain = new CMain(... some args ...);
this.DataContext = this.theMain;
...initialize theMain...
in XAML it looks like this:
Label Content="{Binding Path=MyObject.SomeString}" Name="label1"/>
Label Content="{Binding Path=MyMidObj.SomeString}" Name="label2"/>
Label Content="{Binding Path=MyCollectionObject.SomeString}" Name="label3"/>
Initialization like I wrote is mostly in other threads than main app thread. Still, in every "state object" there is SomeString property, which calls NotifyPropertyChanged event. SomeString is updated whenever thread change object state. Window GUI has some labels that represents SomeString of proper objects.
I don't know why only MyObject of IMain interface is updating binded label when SomeString of TopObject changes. Labels for MidObj and MyCollectionObject are empty somehow.
Sorry for my english, I hope my question is not to confusing ;)
Thanks
Joe
what happens if you set your binding to:
Label Content="{Binding Path=MyObject.SomeObject.SomeString}" Name="label2"/>
Label Content="{Binding Path=MyObject.TheDict}" Name="label3"/>
I'm sorta at a loss to why this doesn't work considering I got it from working code, just added a new level of code, but here's what I have. Basically, when I bind the ViewModel to a list, the binding picks up when Items are added to a collection. However, if an update occurs to the item that is bound, it doesn't get updated. Basically, I have an ObservableCollection that contains a custom class with a string value. When that string value gets updated I need it to update the List.
Right now, when I debug, the list item does get updated correctly, but the UI doesn't reflect the change. If I set the bound item to a member variable and null it out then reset it to the right collection it will work, but not desired behavior.
Here is a mockup of the code, hopefully someone can tell me where I am wrong. Also, I've tried implementing INofityPropertyChanged at every level in the code below.
public class Class1
{
public string ItemName;
}
public class Class2
{
private Class2 _items;
private Class2() //Singleton
{
_items = new ObservableCollection<Class1>();
}
public ObservableCollection<Class1> Items
{
get { return _items; }
internal set
{
_items = value;
}
}
}
public class Class3
{
private Class2 _Class2Instnace;
private Class3()
{
_Class2Instnace = Class2.Instance;
}
public ObservableCollection<Class1> Items2
{
get {return _Class2Instnace.Items; }
}
}
public class MyViewModel : INofityPropertyChanged
{
private Class3 _myClass3;
private MyViewModel()
{
_myClass3 = new Class3();
}
private BindingItems
{
get { return _myClass3.Items2; } // Binds when adding items but not when a Class1.ItemName gets updated.
}
}
The answer to your question is that Class1 needs to implement INotifyPropertyChanged.
public class Class1 : INotifyPropertyChanged
{
private string _ItemName;
public string ItemName
{
get { return _ItemName; }
set
{
_ItemName = value;
NotifyPropertyChanged("ItemName");
}
}
private void NotifyPropertyChanged(string name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public event PropertyChangedEventHandler PropertyChanged;
}