ObservableCollection Remove/Add methods not work even if the item in the list












1















I have a little issue with adding and removing items from collection.



    private ObservableCollection<PrintDocumentSettingsModel> _AllPrintingFormats;
public ObservableCollection<PrintDocumentSettingsModel> PrintingFormats
{
get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
}

private bool _IsStandartPrinter;
public bool IsStandartPrinter
{
get { return _IsStandartPrinter; }
set
{
_IsStandartPrinter = value;
OnPropertyChanged("IsStandartPrinter");
OnPropertyChanged("PrintingFormats");
}
}

private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
PrintingFormats.Contains(SelectedFormat))
{
PrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


Method DeleteFormat() doesn't work even if the if statement returns true. But if I rewrite DeleteFormat() by replacing PrintingFormats with _AllPrintingFormats the method works properly.



    private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
_AllPrintingFormats.Contains(SelectedFormat))
{
_AllPrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


So what's the trick?










share|improve this question




















  • 2





    Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

    – Everyone
    Nov 21 '18 at 5:55
















1















I have a little issue with adding and removing items from collection.



    private ObservableCollection<PrintDocumentSettingsModel> _AllPrintingFormats;
public ObservableCollection<PrintDocumentSettingsModel> PrintingFormats
{
get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
}

private bool _IsStandartPrinter;
public bool IsStandartPrinter
{
get { return _IsStandartPrinter; }
set
{
_IsStandartPrinter = value;
OnPropertyChanged("IsStandartPrinter");
OnPropertyChanged("PrintingFormats");
}
}

private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
PrintingFormats.Contains(SelectedFormat))
{
PrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


Method DeleteFormat() doesn't work even if the if statement returns true. But if I rewrite DeleteFormat() by replacing PrintingFormats with _AllPrintingFormats the method works properly.



    private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
_AllPrintingFormats.Contains(SelectedFormat))
{
_AllPrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


So what's the trick?










share|improve this question




















  • 2





    Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

    – Everyone
    Nov 21 '18 at 5:55














1












1








1








I have a little issue with adding and removing items from collection.



    private ObservableCollection<PrintDocumentSettingsModel> _AllPrintingFormats;
public ObservableCollection<PrintDocumentSettingsModel> PrintingFormats
{
get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
}

private bool _IsStandartPrinter;
public bool IsStandartPrinter
{
get { return _IsStandartPrinter; }
set
{
_IsStandartPrinter = value;
OnPropertyChanged("IsStandartPrinter");
OnPropertyChanged("PrintingFormats");
}
}

private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
PrintingFormats.Contains(SelectedFormat))
{
PrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


Method DeleteFormat() doesn't work even if the if statement returns true. But if I rewrite DeleteFormat() by replacing PrintingFormats with _AllPrintingFormats the method works properly.



    private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
_AllPrintingFormats.Contains(SelectedFormat))
{
_AllPrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


So what's the trick?










share|improve this question
















I have a little issue with adding and removing items from collection.



    private ObservableCollection<PrintDocumentSettingsModel> _AllPrintingFormats;
public ObservableCollection<PrintDocumentSettingsModel> PrintingFormats
{
get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
}

private bool _IsStandartPrinter;
public bool IsStandartPrinter
{
get { return _IsStandartPrinter; }
set
{
_IsStandartPrinter = value;
OnPropertyChanged("IsStandartPrinter");
OnPropertyChanged("PrintingFormats");
}
}

private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
PrintingFormats.Contains(SelectedFormat))
{
PrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


Method DeleteFormat() doesn't work even if the if statement returns true. But if I rewrite DeleteFormat() by replacing PrintingFormats with _AllPrintingFormats the method works properly.



    private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
_AllPrintingFormats.Contains(SelectedFormat))
{
_AllPrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}


So what's the trick?







c# collections






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 21 '18 at 5:55







Aleksey Pavlov

















asked Nov 21 '18 at 5:50









Aleksey PavlovAleksey Pavlov

418




418








  • 2





    Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

    – Everyone
    Nov 21 '18 at 5:55














  • 2





    Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

    – Everyone
    Nov 21 '18 at 5:55








2




2





Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

– Everyone
Nov 21 '18 at 5:55





Obviously it does not work. The getter in PrintingFormats does not return _AllPrintingFormats. Instead it returns a new object which will be garbage collected later on. Any modification you make will be made on var formats in the get function which will not be reflected on _AllPrintingFormats. In DeleteFormat() use _AllPrintingFormats instead of PrintingFormats

– Everyone
Nov 21 '18 at 5:55












1 Answer
1






active

oldest

votes


















2














That's not a nice way of writing properties. A property should return a private object in your class (whether explicitly or implicitly declared) except on some occasions where the property has nothing to do with any actual private member.



When you write this:



    get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }


You are creating a new object called formats and returning a reference to that object. This has nothing to do with the actual private member _AllPrintingFormats. Therefore, when you call PrintingFormats.Remove(SelectedFormat); it will attempt the operation on formats which was declared and instantiated in the get function of PrintingFormats. This change is not reflected on _AllPrintingFormats as it's performed on a different object.



Furthermore, the change is completely useless since you will not hold any reference to formats and it will be garbage collected later on. The code you have is inefficient both on performance (creation of a new variable in get every time the property is called, AND using LINQ to create the variable) and on space (even after the reference on formats is released, it will not be cleaned directly by GC which means you will have multiple formats zombie objects waiting to be collected and occupying space).



By the way, using LINQ on a collection that is highly likely being accessed by multiple threads is not a very good idea as you can have race conditions. You have to understand that this line:



var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));


Will NOT be determined right away. That is, you will not get the elements meeting the LINQ criteria on this call. This will be resolved after you return formats which means any change made by another thread will yield different results between the line and the actual use of formats



If you want to maintain the property and keep it as is, you can always do what you did in the second part of the question and directly use _AllPrintingFormats. However, I would recommend changing the PrintingFormats into:



get { return _AllPrintingFormats }
set
{
_AllPrintingFormats = value;
OnPropertyChanged("PrintingFormats");
}


And if you really need the LINQ query, you can do it on PrintingFormats instead of it being done by the property.






share|improve this answer


























  • I see. How can I change the get function to return current collection?

    – Aleksey Pavlov
    Nov 21 '18 at 6:09











  • @AlekseyPavlov get { return _AllPrintingFormats; }

    – Everyone
    Nov 21 '18 at 6:12











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53405969%2fobservablecollection-remove-add-methods-not-work-even-if-the-item-in-the-list%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














That's not a nice way of writing properties. A property should return a private object in your class (whether explicitly or implicitly declared) except on some occasions where the property has nothing to do with any actual private member.



When you write this:



    get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }


You are creating a new object called formats and returning a reference to that object. This has nothing to do with the actual private member _AllPrintingFormats. Therefore, when you call PrintingFormats.Remove(SelectedFormat); it will attempt the operation on formats which was declared and instantiated in the get function of PrintingFormats. This change is not reflected on _AllPrintingFormats as it's performed on a different object.



Furthermore, the change is completely useless since you will not hold any reference to formats and it will be garbage collected later on. The code you have is inefficient both on performance (creation of a new variable in get every time the property is called, AND using LINQ to create the variable) and on space (even after the reference on formats is released, it will not be cleaned directly by GC which means you will have multiple formats zombie objects waiting to be collected and occupying space).



By the way, using LINQ on a collection that is highly likely being accessed by multiple threads is not a very good idea as you can have race conditions. You have to understand that this line:



var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));


Will NOT be determined right away. That is, you will not get the elements meeting the LINQ criteria on this call. This will be resolved after you return formats which means any change made by another thread will yield different results between the line and the actual use of formats



If you want to maintain the property and keep it as is, you can always do what you did in the second part of the question and directly use _AllPrintingFormats. However, I would recommend changing the PrintingFormats into:



get { return _AllPrintingFormats }
set
{
_AllPrintingFormats = value;
OnPropertyChanged("PrintingFormats");
}


And if you really need the LINQ query, you can do it on PrintingFormats instead of it being done by the property.






share|improve this answer


























  • I see. How can I change the get function to return current collection?

    – Aleksey Pavlov
    Nov 21 '18 at 6:09











  • @AlekseyPavlov get { return _AllPrintingFormats; }

    – Everyone
    Nov 21 '18 at 6:12
















2














That's not a nice way of writing properties. A property should return a private object in your class (whether explicitly or implicitly declared) except on some occasions where the property has nothing to do with any actual private member.



When you write this:



    get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }


You are creating a new object called formats and returning a reference to that object. This has nothing to do with the actual private member _AllPrintingFormats. Therefore, when you call PrintingFormats.Remove(SelectedFormat); it will attempt the operation on formats which was declared and instantiated in the get function of PrintingFormats. This change is not reflected on _AllPrintingFormats as it's performed on a different object.



Furthermore, the change is completely useless since you will not hold any reference to formats and it will be garbage collected later on. The code you have is inefficient both on performance (creation of a new variable in get every time the property is called, AND using LINQ to create the variable) and on space (even after the reference on formats is released, it will not be cleaned directly by GC which means you will have multiple formats zombie objects waiting to be collected and occupying space).



By the way, using LINQ on a collection that is highly likely being accessed by multiple threads is not a very good idea as you can have race conditions. You have to understand that this line:



var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));


Will NOT be determined right away. That is, you will not get the elements meeting the LINQ criteria on this call. This will be resolved after you return formats which means any change made by another thread will yield different results between the line and the actual use of formats



If you want to maintain the property and keep it as is, you can always do what you did in the second part of the question and directly use _AllPrintingFormats. However, I would recommend changing the PrintingFormats into:



get { return _AllPrintingFormats }
set
{
_AllPrintingFormats = value;
OnPropertyChanged("PrintingFormats");
}


And if you really need the LINQ query, you can do it on PrintingFormats instead of it being done by the property.






share|improve this answer


























  • I see. How can I change the get function to return current collection?

    – Aleksey Pavlov
    Nov 21 '18 at 6:09











  • @AlekseyPavlov get { return _AllPrintingFormats; }

    – Everyone
    Nov 21 '18 at 6:12














2












2








2







That's not a nice way of writing properties. A property should return a private object in your class (whether explicitly or implicitly declared) except on some occasions where the property has nothing to do with any actual private member.



When you write this:



    get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }


You are creating a new object called formats and returning a reference to that object. This has nothing to do with the actual private member _AllPrintingFormats. Therefore, when you call PrintingFormats.Remove(SelectedFormat); it will attempt the operation on formats which was declared and instantiated in the get function of PrintingFormats. This change is not reflected on _AllPrintingFormats as it's performed on a different object.



Furthermore, the change is completely useless since you will not hold any reference to formats and it will be garbage collected later on. The code you have is inefficient both on performance (creation of a new variable in get every time the property is called, AND using LINQ to create the variable) and on space (even after the reference on formats is released, it will not be cleaned directly by GC which means you will have multiple formats zombie objects waiting to be collected and occupying space).



By the way, using LINQ on a collection that is highly likely being accessed by multiple threads is not a very good idea as you can have race conditions. You have to understand that this line:



var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));


Will NOT be determined right away. That is, you will not get the elements meeting the LINQ criteria on this call. This will be resolved after you return formats which means any change made by another thread will yield different results between the line and the actual use of formats



If you want to maintain the property and keep it as is, you can always do what you did in the second part of the question and directly use _AllPrintingFormats. However, I would recommend changing the PrintingFormats into:



get { return _AllPrintingFormats }
set
{
_AllPrintingFormats = value;
OnPropertyChanged("PrintingFormats");
}


And if you really need the LINQ query, you can do it on PrintingFormats instead of it being done by the property.






share|improve this answer















That's not a nice way of writing properties. A property should return a private object in your class (whether explicitly or implicitly declared) except on some occasions where the property has nothing to do with any actual private member.



When you write this:



    get
{
var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
if (!formats.Contains(SelectedFormat))
SelectedFormat = formats.FirstOrDefault();
return formats;
}
set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }


You are creating a new object called formats and returning a reference to that object. This has nothing to do with the actual private member _AllPrintingFormats. Therefore, when you call PrintingFormats.Remove(SelectedFormat); it will attempt the operation on formats which was declared and instantiated in the get function of PrintingFormats. This change is not reflected on _AllPrintingFormats as it's performed on a different object.



Furthermore, the change is completely useless since you will not hold any reference to formats and it will be garbage collected later on. The code you have is inefficient both on performance (creation of a new variable in get every time the property is called, AND using LINQ to create the variable) and on space (even after the reference on formats is released, it will not be cleaned directly by GC which means you will have multiple formats zombie objects waiting to be collected and occupying space).



By the way, using LINQ on a collection that is highly likely being accessed by multiple threads is not a very good idea as you can have race conditions. You have to understand that this line:



var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));


Will NOT be determined right away. That is, you will not get the elements meeting the LINQ criteria on this call. This will be resolved after you return formats which means any change made by another thread will yield different results between the line and the actual use of formats



If you want to maintain the property and keep it as is, you can always do what you did in the second part of the question and directly use _AllPrintingFormats. However, I would recommend changing the PrintingFormats into:



get { return _AllPrintingFormats }
set
{
_AllPrintingFormats = value;
OnPropertyChanged("PrintingFormats");
}


And if you really need the LINQ query, you can do it on PrintingFormats instead of it being done by the property.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 21 '18 at 6:20

























answered Nov 21 '18 at 6:02









EveryoneEveryone

819318




819318













  • I see. How can I change the get function to return current collection?

    – Aleksey Pavlov
    Nov 21 '18 at 6:09











  • @AlekseyPavlov get { return _AllPrintingFormats; }

    – Everyone
    Nov 21 '18 at 6:12



















  • I see. How can I change the get function to return current collection?

    – Aleksey Pavlov
    Nov 21 '18 at 6:09











  • @AlekseyPavlov get { return _AllPrintingFormats; }

    – Everyone
    Nov 21 '18 at 6:12

















I see. How can I change the get function to return current collection?

– Aleksey Pavlov
Nov 21 '18 at 6:09





I see. How can I change the get function to return current collection?

– Aleksey Pavlov
Nov 21 '18 at 6:09













@AlekseyPavlov get { return _AllPrintingFormats; }

– Everyone
Nov 21 '18 at 6:12





@AlekseyPavlov get { return _AllPrintingFormats; }

– Everyone
Nov 21 '18 at 6:12


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53405969%2fobservablecollection-remove-add-methods-not-work-even-if-the-item-in-the-list%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

A Topological Invariant for $pi_3(U(n))$