I've been trying for two days now to figure this out, and repeatedly searching for answers. It seems like it should be so simple.
The goal:
I have two comboboxs. One is for an object Country, the other is for CountrySubdivision. (EG USA has States, Canada has Provinces, etc.) I want to load the form and have both the Country and CountrySubdivision in place.
Project has a Country and CountrySubdivions. Country has an ObservableCollection of CountrySubdivision. All objects are INotifyCollectionChanged. So here's where it gets irritating. The bindings "work." In that, if I change the values and save, the proper values are put back into the database. However, every time I open up the application, CountrySubdivision starts empty. The backing value is still set, but the combo box isn't set.
Here are the applicable bindings:
<ComboBox
x:Name="uiProjectCountrySubdivisions"
DisplayMemberPath="Name"
SelectedItem="{Binding Project.ProjectCountrySubdivision}"
ItemsSource="{Binding Project.ProjectCountry.CountrySubdivisions}"
FontSize="10.667" />
<ComboBox
x:Name="uiProjectCountry"
SelectedItem="{Binding Project.ProjectCountry}"
ItemsSource="{Binding Countries}"
DisplayMemberPath="Name"
FontSize="10.667" />
And as requested, here are the (severly shorted) classes.
public class Project : BaseNotifyPropertyChanged
{
private Guid _projectId;
public virtual Guid ProjectId
{
get { return _projectId; }
set
{
if (_projectId != value)
{
_projectId = value;
OnPropertyChanged(() => ProjectId);
}
}
}
private string _projectName;
public virtual string ProjectName
{
get { return _projectName; }
set
{
if (_projectName != value)
{
_projectName = value;
OnPropertyChanged(() => ProjectName);
}
}
}
private string _projectNumber;
public virtual string ProjectNumber
{
get { return _projectNumber; }
set
{
if (_projectNumber != value)
{
_projectNumber = value;
OnPropertyChanged(() => ProjectNumber);
}
}
}
private string _projectAddressLineOne;
public virtual string ProjectAddressLineOne
{
get { return _projectAddressLineOne; }
set
{
if (_projectAddressLineOne != value)
{
_projectAddressLineOne = value;
OnPropertyChanged(() => ProjectAddressLineOne);
}
}
}
private string _projectAddressLineTwo;
public virtual string ProjectAddressLineTwo
{
get { return _projectAddressLineTwo; }
set
{
if (_projectAddressLineTwo != value)
{
_projectAddressLineTwo = value;
OnPropertyChanged(() => ProjectAddressLineTwo);
}
}
}
private string _projectCity;
public virtual string ProjectCity
{
get { return _projectCity; }
set
{
if (_projectCity != value)
{
_projectCity = value;
OnPropertyChanged(() => ProjectCity);
}
}
}
private string _projectZip;
public virtual string ProjectZip
{
get { return _projectZip; }
set
{
if (_projectZip != value)
{
_projectZip = value;
OnPropertyChanged(() => ProjectZip);
}
}
}
private Country _projectCountry;
public virtual Country ProjectCountry
{
get { return _projectCountry; }
set
{
if (_projectCountry != value)
{
_projectCountry = value;
OnPropertyChanged(() => ProjectCountry);
}
}
}
private CountrySubdivision _projectCountrySubdivision;
public virtual CountrySubdivision ProjectCountrySubdivision
{
get { return _projectCountrySubdivision; }
set
{
if (_projectCountrySubdivision != value)
{
_projectCountrySubdivision = value;
OnPropertyChanged(() => ProjectCountrySubdivision);
}
}
}
}
public class Country : BaseNotifyPropertyChanged
{
private int _id;
public virtual int CountryId
{
get { return _id; }
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged(() => CountryId);
}
}
}
private string _name;
public virtual string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(() => Name);
}
}
}
private string _code;
public virtual string Code
{
get
{
return _code;
}
set
{
if (_code != value)
{
_code = value;
OnPropertyChanged(() => Code);
}
}
}
private ObservableCollection<CountrySubdivision> _countrySubdivisions = new ObservableCollection<CountrySubdivision>();
public virtual ObservableCollection<CountrySubdivision> CountrySubdivisions
{
get
{
return _countrySubdivisions;
}
set
{
if (_countrySubdivisions != value)
{
_countrySubdivisions = value;
OnPropertyChanged(() => CountrySubdivisions);
}
}
}
private string _subdivisionTypeShortDescription;
public virtual string SubdivisionTypeShortDescription
{
get
{
return _subdivisionTypeShortDescription;
}
set
{
if (_subdivisionTypeShortDescription != value)
{
_subdivisionTypeShortDescription = value;
OnPropertyChanged(() => SubdivisionTypeShortDescription);
}
}
}
private string _subdivisionTypeLongDescription;
public virtual string SubdivisionTypeLongDescription
{
get
{
return _subdivisionTypeLongDescription;
}
set
{
if (_subdivisionTypeLongDescription != value)
{
_subdivisionTypeLongDescription = value;
OnPropertyChanged(() => SubdivisionTypeLongDescription);
}
}
}
}
public class CountrySubdivision : BaseNotifyPropertyChanged
{
private int _id;
public virtual int CountrySubdivisionId
{
get { return _id; }
set
{
if (_id != value)
{
_id = value;
OnPropertyChanged(() => CountrySubdivisionId);
}
}
}
private string _name;
public virtual string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
OnPropertyChanged(() => Name);
}
}
}
private Country _country;
public virtual Country Country
{
get { return _country; }
set
{
if (_country != value)
{
_country = value;
OnPropertyChanged(() => Country);
}
}
}
}
public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
public virtual event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(Expression<Func<object>> propertySelector)
{
//Stuff that turns () => Property into a fired Property Changed event.
}
}
Please help!!
Is the SelectedItem on your ComboBox an object? If so, is it the exact same instance that exists in the "Countries" collection? Remember that for WPF to consider something "Selected" it must be able to find the "SelectedItem" in the "Countries" collection. If these types differ or instances differ that won't work.
I prefer binding my ComboBoxes as follows:
IDictionary<int, string> Countries
int? CountryId
<ComboBox
ItemsSource="{Binding Countries}"
SelectedValue="{Binding CountryId}"
SelectedValuePath="Key"
DisplayMemberPath="Value"/>
Still, as Alex asks, please list the relevant class definitions and relevant properties too.
Related
I have a view which opens an idialog that I contain a datagrid. I select certain rows and send back those as a list to the view but all I search I just found ResultButton return for idialog. How I can send back a custom value like a list or anything else ?
My iDialog ViewModel :
public DelegateCommand<string> CloseCommand { get; set; }
public DelegateCommand<string> AttachCommand { get; set; }
private string _txtSearch;
public string txtSearch
{
get { return _txtSearch; }
set { SetProperty(ref _txtSearch, value); }
}
public List<GE_Drawing> SelectedDrawings { get; set; }
private ObservableCollection<GE_Drawing> _DrawingList= new ObservableCollection<GE_Drawing>();
public ObservableCollection<GE_Drawing> DrawingList
{
get { return _DrawingList; }
set { SetProperty(ref _DrawingList, value); }
}
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set { SetProperty(ref _IsSelected, value); }
}
public GE_DrawingAttachViewModel()
{
LoadList();
CloseCommand = new DelegateCommand<string>(onClose);
AttachCommand = new DelegateCommand<string>(onAttach);
}
private void onAttach(string parameter)
{
ButtonResult result = new ButtonResult();
var records = DrawingList.Where(x => x.IsSelected == true).ToList();
if(records.Count>0)
{
SelectedDrawings = records;
}
//result = ButtonResult.OK;
//RaiseRequestClose(new DialogResult(result));
}
private void RaiseRequestClose(DialogResult dialogResult)
{
RequestClose?.Invoke(dialogResult);
}
private void onClose(string parameter)
{
ButtonResult result = new ButtonResult();
result = ButtonResult.Cancel;
RaiseRequestClose(new DialogResult(result));
}
private string _title="Drawing List";
public string Title
{
get => _title;
set => SetProperty(ref _title, value);
}
public event Action<IDialogResult> RequestClose;
public bool CanCloseDialog()
{
return true;
}
public void OnDialogClosed()
{
}
public void OnDialogOpened(IDialogParameters parameters)
{
}
public async void LoadList()
{
GenericDataService<GE_Drawing> generic = new GenericDataService<GE_Drawing>();
DrawingList.AddRange(await generic.GetAll());
}
}
As written above I have an OnAttach which should send back my SelectedDrawings variable to the view but I dont know how to do that.
I have found the answer... IdialogResult have parameter with a value could be set to in dialog and get the value in the callback using a key.
private void openDialog()
{
DialogParameters parameter = new DialogParameters();
_dialogService.ShowDialog("GE_DrawingAttach", parameter, r =>
{
if(r.Result==ButtonResult.OK)
{
DrawingList = r.Parameters.GetValue<List<GE_Drawing>>("DrawingList");
}
});
}
I have a set of classes that I am using to deserialize JSON into. My program will periodically look for changes to this JSON file, and if it finds any, will push the new data to the properties of these classes using reflection.
I need to find any new items added to the collection of the Item2 class (SocialExportJSON.SocialExportData.Item2) after a successful update.
My JSON classes look like this (there are more but I want to avoid too big a wall of code):
public class Item2 : INotifyPropertyChanged
{
[JsonProperty("type")]
private string type;
public string Type
{
get
{
return type;
}
set
{
if (type != value)
{
type = value;
RaisePropertyChanged("Type");
}
}
}
[JsonProperty("id")]
private string id;
public string ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("postedIso8601")]
private string postedIso8601;
public string PostedIso8601
{
get
{
return postedIso8601;
}
set
{
if (postedIso8601 != value)
{
postedIso8601 = value;
RaisePropertyChanged("PostedIso8601");
}
}
}
[JsonProperty("postedTimestamp")]
private object postedTimestamp;
public object PostedTimestamp
{
get
{
return postedTimestamp;
}
set
{
if (postedTimestamp != value)
{
postedTimestamp = value;
RaisePropertyChanged("PostedTimestamp");
}
}
}
[JsonProperty("engagement")]
private Engagement engagement;
public Engagement Engagement
{
get
{
return engagement;
}
set
{
if (engagement != value)
{
engagement = value;
RaisePropertyChanged("Engagement");
}
}
}
[JsonProperty("source")]
private Source2 source;
public Source2 Source
{
get
{
return source;
}
set
{
if (source != value)
{
source = value;
RaisePropertyChanged("Source");
}
}
}
[JsonProperty("author")]
private Author author;
public Author Author
{
get
{
return author;
}
set
{
if (author != value)
{
author = value;
RaisePropertyChanged("Author");
}
}
}
[JsonProperty("content")]
private Content content;
public Content Content
{
get
{
return content;
}
set
{
if (content != value)
{
content = value;
RaisePropertyChanged("Content");
}
}
}
[JsonProperty("location")]
private Location location;
public Location Location
{
get
{
return location;
}
set
{
if (location != value)
{
location = value;
RaisePropertyChanged("Location");
}
}
}
[JsonProperty("publication")]
private Publication publication;
public Publication Publication
{
get
{
return publication;
}
set
{
if (publication != value)
{
publication = value;
RaisePropertyChanged("Publication");
}
}
}
[JsonProperty("metadata")]
private Metadata metadata;
public Metadata Metadata
{
get
{
return metadata;
}
set
{
if (metadata != value)
{
metadata = value;
RaisePropertyChanged("Metadata");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public class SocialExportData : INotifyPropertyChanged
{
[JsonProperty("dataType")]
private string dataType;
public string DataType
{
get
{
return dataType;
}
set
{
if (dataType != value)
{
dataType = value;
RaisePropertyChanged("DataType");
}
}
}
[JsonProperty("id")]
private int id;
public int ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("story")]
private Story story;
public Story Story
{
get
{
return story;
}
set
{
if (story != value)
{
story = value;
RaisePropertyChanged("Story");
}
}
}
[JsonProperty("order")]
private string order;
public string Order
{
get
{
return order;
}
set
{
if (order != value)
{
order = value;
RaisePropertyChanged("Order");
}
}
}
[JsonProperty("lifetime")]
private string lifetime;
public string Lifetime
{
get
{
return lifetime;
}
set
{
if (lifetime != value)
{
lifetime = value;
RaisePropertyChanged("Lifetime");
}
}
}
[JsonProperty("maxAge")]
private int maxAge;
public int MaxAge
{
get
{
return maxAge;
}
set
{
if (maxAge != value)
{
maxAge = value;
RaisePropertyChanged("MaxAge");
}
}
}
[JsonProperty("maxSize")]
private int maxSize;
public int MaxSize
{
get
{
return maxSize;
}
set
{
if (maxSize != value)
{
maxSize = value;
RaisePropertyChanged("MaxSize");
}
}
}
[JsonProperty("consumeCount")]
private int consumeCount;
public int ConsumeCount
{
get
{
return consumeCount;
}
set
{
if (consumeCount != value)
{
consumeCount = value;
RaisePropertyChanged("ConsumeCount");
}
}
}
[JsonProperty("consumeInterval")]
private int consumeInterval;
public int ConsumeInterval
{
get
{
return consumeInterval;
}
set
{
if (consumeInterval != value)
{
consumeInterval = value;
RaisePropertyChanged("ConsumeInterval");
}
}
}
[JsonProperty("items")]
private ObservableCollection<Item2> items;
public ObservableCollection<Item2> Items
{
get
{
return items;
}
set
{
if (items != value)
{
items = value;
RaisePropertyChanged("Items");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public class SocialExportJSON : INotifyPropertyChanged
{
[JsonProperty("id")]
private string id;
public string ID
{
get
{
return id;
}
set
{
if (id != value)
{
id = value;
RaisePropertyChanged("ID");
}
}
}
[JsonProperty("ttl")]
private int ttl;
public int TTL
{
get
{
return ttl;
}
set
{
if (ttl != value)
{
ttl = value;
RaisePropertyChanged("TTL");
}
}
}
[JsonProperty("serial")]
private long serial;
public long Serial
{
get
{
return serial;
}
set
{
if (serial != value)
{
serial = value;
RaisePropertyChanged("Serial");
}
}
}
[JsonProperty("formatType")]
private string formatType;
public string FormatType
{
get
{
return formatType;
}
set
{
if (formatType != value)
{
formatType = value;
RaisePropertyChanged("FormatType");
}
}
}
[JsonProperty("modifiedIso8601")]
private string modifiedIso8601;
public string ModifiedIso8601
{
get
{
return modifiedIso8601;
}
set
{
if (modifiedIso8601 != value)
{
modifiedIso8601 = value;
RaisePropertyChanged("ModifiedIso8601");
}
}
}
[JsonProperty("modifiedTimestamp")]
private long modifiedTimestamp;
public long ModifiedTimestamp
{
get
{
return modifiedTimestamp;
}
set
{
if (modifiedTimestamp != value)
{
modifiedTimestamp = value;
RaisePropertyChanged("ModifiedTimestamp");
}
}
}
[JsonProperty("timezone")]
private string timezone;
public string Timezone
{
get
{
return timezone;
}
set
{
if (timezone != value)
{
timezone = value;
RaisePropertyChanged("Timezone");
}
}
}
[JsonProperty("dataType")]
private string dataType;
public string DataType
{
get
{
return dataType;
}
set
{
if (dataType != value)
{
dataType = value;
RaisePropertyChanged("DataType");
}
}
}
[JsonProperty("exports")]
private ObservableCollection<SocialExportData> exports;
public ObservableCollection<SocialExportData> Exports
{
get
{
return exports;
}
set
{
if (exports != value)
{
exports = value;
RaisePropertyChanged("Exports");
}
}
}
//Event handling
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
//Console.WriteLine("Updated");
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
In another class, I have a method to deserialize to a global instance of my JSON class. It looks like this:
public SocialExportJSON socialExportData;
private async void DownloadAndDeserializeJSONAsync()
{
try
{
//Create a web client with the supplied credentials
var exportClient = new WebClient { Credentials = new NetworkCredential(uName, pw), Encoding = Encoding.UTF8};
//Create a task to download the JSON string and wait for it to finish
var downloadTask = Task.Run(() => exportClient.DownloadString(new Uri(eURL)));
downloadTask.Wait();
//Get the string from the task
var JSONString = await downloadTask;
//Create a task to deserialize the JSON from the last task
var DeserializeTask = Task.Run(() => JsonConvert.DeserializeObject<SocialExportJSON>(JSONString));
DeserializeTask.Wait();
SocialExportJSON sej = await DeserializeTask;
//Check the timestamp first to see if we should change the data
if(socialExportData == null)
{
//Get the data from the task
socialExportData = await DeserializeTask;
}
else if(sej.ModifiedTimestamp != socialExportData.ModifiedTimestamp)
{
//Get the data from the task
SocialExportJSON newData = await DeserializeTask;
GetNewItems(newData);
SetNewData(newData);
//Call the exportUpdated event when the task has finished
exportUpdated();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message.ToString());
}
}
In my SetNewData function, shown below, I use reflection to set the properties of my global class. Because I'm setting the whole collection rather than iterating through each of the properties in each of the classes, I can't use the CollectionChanged event to find new items.
public void SetNewData(SocialExportJSON newData)
{
//Loop through each of the properties and copy from source to target
foreach (PropertyInfo pi in socialExportData.GetType().GetProperties())
{
if (pi.CanWrite)
{
pi.SetValue(socialExportData, pi.GetValue(newData, null), null);
}
}
}
Is there a way I can modify my SetNewData function in such a way that it calls CollectionChanged? If not, what would be the best way to go about getting any new additions to my collection of Item2?
In my Main function. I create an instance of my class called SocialExport like so:
SocialExport s = new SocialExport("http://example.json", "example", "example");.
This class is where the global instance of my JSON class is contained, and my event handler is added like so
s.socialExportData.Exports[0].Items.CollectionChanged += CollectionChanged;
Then you are hooking up an event handler for the CollectionChanged event for that particular instance of ObservableCollection<Item2>.
If you create a new ObservableCollection<Item2>, you obviously must hook up an event handler to this one as well. The event handler that is associated with the old object won't be invoked when new items are added to the new instance.
So whenever a new ObservableCollection<Item2> is created, using deserialization or not, you should hook up a new event handler.
You could probably do this in your DownloadAndDeserializeJSONAsync method. The other option would be to create only one instance of the collection and remove and add items from/to this one.
I'm having trouble displaying the results in the AutoSuggestBox on Windows Phone 8.1. I'm using MVVM Light to bind my itemsource to the Autosuggestbox.
<AutoSuggestBox Header="Van" Text="{Binding SearchTextFrom, Mode=TwoWay}" ItemsSource="{Binding suggestionFrom}">
<AutoSuggestBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding description}"/>
</DataTemplate>
</AutoSuggestBox.ItemTemplate>
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="TextChanged">
<core:InvokeCommandAction Command="{Binding SearchChangedFrom}">
</core:InvokeCommandAction>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</AutoSuggestBox>
My ViewModel
private RelayCommand _SearchChangedFrom;
public RelayCommand SearchChangedFrom
{
get
{
return _SearchChangedFrom ?? (_SearchChangedFrom = new RelayCommand(
async () =>
{
if (string.IsNullOrWhiteSpace(user.countrycode))
{
Debug.WriteLine("Could not autocomplete the country because there was no country code provided.");
return;
}
var predictions = await _Service.GetGoogleMapsSuggestionFromQuery(user.countrycode, SearchTextFrom);
suggestionFrom = predictions;
}));
}
}
private List<Prediction> _suggestionFrom;
public List<Prediction> suggestionFrom
{
get { return _suggestionFrom; }
set
{
Set<List<Prediction>>(() => suggestionFrom, ref _suggestionFrom, value);
Debug.WriteLine(suggestionFrom.Count + " were received. Displayong them in the autosuggestbox");
foreach (Prediction prediction in _suggestionFrom)
{
Debug.WriteLine(("Predicition: " + prediction.description));
}
}
}
The objects are set and are not null.
So why don't they show up?
UPDATE
My Model
public class Prediction : ObservableObject
{
private string _description;
public string description
{
get { return _description; }
set{Set<string>(() => description, ref _description, value);}
}
private string _id;
public string id
{
get { return _id; }
set { Set<string>(() => id, ref _id, value); }
}
private List<MatchedSubstring> _matchedSubstrings;
public List<MatchedSubstring> matched_substrings
{
get { return _matchedSubstrings; }
set{Set<List<MatchedSubstring>>(() => matched_substrings, ref _matchedSubstrings, value);}
}
private string _place_id;
public string place_id
{
get { return _place_id; }
set { Set<string>(() => place_id, ref _place_id, value); }
}
private string _reference;
public string reference
{
get { return _reference; }
set { Set<string>(() => reference, ref _reference, value); }
}
private List<Term> _terms;
public List<Term> terms
{
get { return _terms; }
set { Set<List<Term>>(() => terms, ref _terms, value); }
}
private List<string> _types;
public List<string> types
{
get { return _types; }
set { Set<List<String>>(() => types, ref _types, value); }
}
public override string ToString()
{
return this.description;
}
}
Use
public ObservableCollection<Prediction> SuggestionFrom { get; set; }
instead
public List<Prediction> SuggestionFrom { get; set; }
ObservableCollection is notify user interface about any changes of your Predictions (add or delete)
I am using Telerik's WPF controls with Caliburn.Micro. In particular the DataForm control. I am trying to bind it to an object that has the following make up.
public class FrequencyMap : BindableBase
{
private Guid id;
public Guid ID
{
get { return id; }
set
{
id = value;
OnPropertyChanged();
}
}
private string procedureCodeId;
public string ProcedureCodeId
{
get { return procedureCodeId; }
set
{
procedureCodeId = value;
OnPropertyChanged();
}
}
private FrequencyChoice frequency;
public FrequencyChoice Frequency
{
get { return frequency; }
set
{
frequency = value;
OnPropertyChanged();
}
}
private DateTime effectiveDate;
public DateTime EffectiveDate
{
get { return effectiveDate; }
set
{
effectiveDate = value;
OnPropertyChanged();
}
}
private DateTime? terminateDate;
public DateTime? TerminateDate
{
get { return terminateDate; }
set
{
terminateDate = value;
OnPropertyChanged();
}
}
}
and then the FrequencyChoice object looks like this:
public class FrequencyChoice : BindableBase
{
private int id;
private string modifiedUser;
public int ID
{
get { return id; }
set
{
id = value; OnPropertyChanged();
}
}
private string code;
public string Code
{
get { return code; }
set
{
code = value; OnPropertyChanged();
}
}
private string name;
public string Name
{
get { return name; }
set
{
name = value; OnPropertyChanged();
}
}
private string description;
public string Description
{
get { return description; }
set
{
description = value; OnPropertyChanged();
}
}
private string calculationDescription;
public string CalculationDescription
{
get { return calculationDescription; }
set
{
calculationDescription = value; OnPropertyChanged();
}
}
private DateTime inactiveDate;
public DateTime InactiveDate
{
get { return inactiveDate; }
set
{
inactiveDate = value; OnPropertyChanged();
}
}
public string ModifiedUser
{
get
{
return this.modifiedUser;
}
set
{
this.modifiedUser = value;
OnPropertyChanged();
}
}
}
This works quite well except for the Frequency property. How do I get that to work properly. Do I have to use an Enum like this article? Data Forms in your XAML
If so how would I link the two?
I guess what you want is 1 Frequency Map with Many FrequencyChoices relationship
1st I would change the property to inherit from PropertyChangedBase
public class FrequencyChoice : PropertyChangedBase
{
}
then change your properties as below
private BindableCollection<FrequencyChoice> frequencyChoices;
public BindableCollection<FrequencyChoice> FrequencyChoices
{
get
{
return this.frequencyChoices;
}
set
{
if (Equals(value, this.frequencyChoices))
{
return;
}
this.frequencyChoices = value;
this.NotifyOfPropertyChange(() => this.FrequencyChoices);
}
}
I am not really sure what is BindableBase (from google is Prism but hey ur using Caliburn so use PropertyChangedBase) but if want to still use it go ahead but just make sure it handle change notification for you
as each map has many choices you will need collection to store the choices
I have a product which has viewModel:
ProductViewModel
private int _id;
private string _name;
private string _type;
private int _selectedID;
public ProductViewModel(int id, string name, string type)
{
_ id = id;
_ name = name;
_ type = type;
}
public int ProductID
{
get { return _id; }
set { _id = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Type
{
get { return _type; }
set { _type = value; }
}
public int Selected
{
get { return _selected; }
set { _selected = value; }
}
And for showing a list of products I have another ViewModel:
ProductListViewModel
private PagedResult<ProductViewModel> _pagedResult;
private string _sortColumn = "Id";
private string _sortOrder = "ASC";
public LostAssetsListViewModel(PagedResult< ProductViewModel > products)
{
_pagedResult = products;
}
public PagedResult<ProductViewModel> List
{
get { return _pagedResult; }
set { _pagedResult = value; }
}
public string SortColumn
{
get { return _sortColumn; }
set { _sortColumn = value; }
}
public string SortOrder
{
get { return _sortOrder; }
set { _sortOrder = value; }
}
And in my View I'm using Product LisViewModel to show a list of products. And in every product I want to add radio button (to select that product)
<% = Html.RadioButtonFor(m => m.List[i].Selected, "false", Model.List[i]. ProductID)%>
For getting all the data in my controller I created ProductInputModel:
ProductInputModel
private int _id;
private string _name;
private string _type;
private int _selectedID;
public ProductInputModel(int id, string name, string type)
{
_ id = id;
_ name = name;
_ type = type;
}
public int ProductID
{
get { return _id; }
set { _id = value; }
}
public string Name
{
get { return _name; }
set { _name = value; }
}
public string Type
{
get { return _type; }
set { _type = value; }
}
public int Selected
{
get { return _selected; }
set { _selected = value; }
}
In my controller input is empty :
[HttpPost]
public ActionResult Details(ProductInputModel input)
{}
I can't figure out whydata from ProductViewModel not passes to ProductInputModel. How I should get the selected product through ViewModels?
Your view models must have default parameterless constructors if you want to use them as action parameters. Otherwise the default model binder will not be able to instantiate it. You should make sure that you have a parameterless constructor to your ProductInputModel.