c# - WPF, covariance, contravariance, and binding in .Net -
i need make settings manager can't use appsettings or applicationsettings because need specific behaviour (adding/removing settings @ runtime, loading from/saving in multiple files...).
the problem i'm encountering finding solution end result want. here exemple of should in use case :
public partial class mywindow : window { private settingsmanager _settingsmanager; public myclass() { _settingsmanager.add(new option(){name = "option1", displayname = "option 1", defaultvalue = "sometext", value = "sometext"}); _settingsmanager.add(new option(){name = "option2", displayname = "option 2", defaultvalue = 5}); _settingsmanager.add(new option(){name = "option3", displayname = "option 3"}); _settingsmanager["option2"] = 10; _settingsmanager["option3"].defaultvalue = brushes.black; _settingsmanager["option3"] = brushes.white; datacontext = _settingsmanager; } }
with it's corresponding xaml file :
<window x:class="anotherproject.mywindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" title="mainwindow" height="350" width="525" loaded="window_loaded"> <grid> <itemscontrol itemssource="{binding}"> <itemscontrol.resources> <datatemplate datatype="{x:type string}"> <label content="{binding}"/> </datatemplate> <datatemplate datatype="{x:type int}"> <label content="{binding}" foreground="red"/> </datatemplate> <datatemplate datatype="{x:type brush}"> <label content="{binding tostring}" foreground="{binding}"/> </datatemplate> </itemscontrol.resources> </itemscontrol> </grid>
i aware wpf not support int , string types , produces errors, used demonstrative example, real types not produce errors.
i tried inheriting settingsproperty, used appsettings, seemed complex i'm trying , couldn't assign values without casting.
i tried using generics there problem in type recognition. following line did not work unless object cast appropriate type :
_settingsmanager["option2"] = 10;
i know ways achieve of use case parts separately, not 1 of above mentioned.
is possible achieve that?
update : here settingmanager looks like
public class settingsmanager : observablecollection<option> { public settingsmanager() { } public settingsmanager(ienumerable<option> options) { if (options != null) { foreach(var option in options) { this.add(option); } } } public option this[string key] { { return this.where(x => x.name == key).firstordefault(); } set { var res = this.first(x => x.name == key); if (res != null) { this.setitem(this.indexof(res), value); } else this.add(value); } } public settingsmanager addrange(ienumerable<option> options) { if (options != null) { foreach(var option in options) { this.add(option); } } return this; } public void resetall() { this.tolist().foreach(x => x.reset()); } }
the itemscontrol
has itemssource
set collection of option
, meaning each data item of type option
. datatemplate
datatype cannot filter on different types of value
(a property of option
) apply different templates. in case should use datatemplateselector
, define datatemplates resources in xaml convenience (we can find them in code behind inside selecttemplate
method):
public class optiontemplateselector : datatemplateselector { public override datatemplate selecttemplate(object item, dependencyobject container){ var option = item option; if(option != null){ var itemcontainer = container frameworkelement; if(option.value int){ return itemcontainer.findresource("intoption") datatemplate; } else if(option.value string){ return itemcontainer.findresource("stringoption") datatemplate; } else if(option.value brush){ return itemcontainer.findresource("brushoption") datatemplate; } } return null; } }
define template selector resource in xaml:
<local:optiontemplateselector x:key="ot">
the remaining xaml:
<itemscontrol itemssource="{binding}" itemtemplateselector="{staticresource ot}"> <itemscontrol.resources> <datatemplate x:key="stringoption"> <label content="{binding value}"/> </datatemplate> <datatemplate x:key="intoption"> <label content="{binding value}" foreground="red"/> </datatemplate> <datatemplate x:key="brushoption"> <label content="{binding value}" foreground="{binding}"/> </datatemplate> </itemscontrol.resources> </itemscontrol>
Comments
Post a Comment