AutoSuggestBox not showing results - c#

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)

Related

WPF Prism send parameter back from idialog to view

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");
}
});
}

IDataErrorInfo Issue - Initial property values

i have a ViewModel that implements the IDataErrorInfo interface as usual.
Model
public class Computer : Model
{
public Computer(string name, string ip, string mac, string broadcastIp)
{
Name = name;
Ip = ip;
Mac = mac;
BroadcastIp = broadcastIp;
}
public Computer()
{
Name = "neuer Computer";
Mac = string.Empty;
Ip = string.Empty;
BroadcastIp = string.Empty;
}
[NotMapped]
public ComputerState ComputerState { get; set; }
public string Name { get; set; }
public string Ip { get; set; }
public string Mac { get; set; }
public string BroadcastIp { get; set; }
public virtual Room Room { get; set; }
}
ViewModel
public class ComputerViewModel : ViewModel<Computer>, IListItem
{
private bool _IsSelected;
private ComputerOperationMessage _OperationMessage = ComputerOperationMessage.NO_MESSAGE;
public ComputerViewModel(Computer computer) : base(computer)
{
}
public string Name
{
get { return Model.Name; }
set
{
Model.Name = value;
RaisePropertyChanged(nameof(Name));
}
}
public RoomViewModel Room
{
get { return App.EntityManager.Get<RoomViewModel>().FirstOrDefault(r => r.Model.Equals(Model.Room)); }
set
{
Model.Room = value.Model;
RaisePropertyChanged(nameof(Room));
}
}
public ComputerState State
{
get { return Model.ComputerState; }
set
{
if (value.Equals(Model.ComputerState))
return;
Model.ComputerState = value;
RaisePropertyChanged(nameof(State));
}
}
public string Ip
{
get { return Model.Ip; }
set
{
Model.Ip = value;
RaisePropertyChanged(nameof(Ip));
}
}
public string Mac
{
get { return Model.Mac; }
set
{
Model.Mac = value;
RaisePropertyChanged(nameof(Mac));
}
}
public string BroadcastIp
{
get { return Model.BroadcastIp; }
set
{
Model.BroadcastIp = value;
RaisePropertyChanged(nameof(BroadcastIp));
}
}
/// <summary>
/// UI indicator when a operation like shutdown, reboot, ping etc. is running
/// </summary>
public ComputerOperationMessage OperationMessage
{
get { return _OperationMessage; }
set
{
if (value.Equals(_OperationMessage))
return;
_OperationMessage = value;
RaisePropertyChanged(nameof(OperationMessage));
}
}
public bool IsSelected
{
get { return _IsSelected; }
set
{
_IsSelected = value;
RaisePropertyChanged(nameof(IsSelected));
}
}
public override string ToString()
{
return Name;
}
protected override string ValidateProperty(string property)
{
var computers = App.EntityManager.Get<ComputerViewModel>().ToList();
switch (property)
{
case nameof(Name):
if (string.IsNullOrEmpty(Name))
{
return "Bezeichnung erwartet";
}
if (computers.Any(c => c.Name == Name))
{
return "Bezeichnung bereits vergeben";
}
break;
case nameof(Ip):
if (string.IsNullOrEmpty(Ip))
{
return "Ip erwartet";
}
if (!NetworkCommand.ValidateIp(Ip))
{
return "Ip ungültig";
}
if (computers.Any(c => c.Ip == Ip))
{
return "Ip bereits vergeben";
}
break;
case nameof(Mac):
if (string.IsNullOrEmpty(Mac))
{
return "Mac erwartet";
}
if (!NetworkCommand.ValidateMac(Mac))
{
return "Mac ungültig";
}
if (computers.Any(c => c.Mac == Mac))
{
return "Mac bereits vergeben";
}
break;
case nameof(BroadcastIp):
if (string.IsNullOrEmpty(BroadcastIp))
{
return "Broadcast Ip erwartet";
}
if (!NetworkCommand.ValidateIp(Ip))
{
return "Broadcast Ip ungültig";
}
break;
case nameof(Room):
if (Room == null)
return "Raum wählen";
break;
}
return string.Empty;
}
public abstract class ViewModel : INotifyPropertyChanged, IDataErrorInfo
{
private string _ErrorMessage;
private bool _HasErrors;
public ViewModel()
{
SaveCommand = new RelayCommand(SaveAction);
}
public bool HasErrors
{
get { return _HasErrors; }
set
{
_HasErrors = value;
RaisePropertyChanged(nameof(HasErrors));
}
}
public ICommand SaveCommand { get; }
public Model Model { get; protected set; }
public string this[string property]
{
get
{
_ErrorMessage = ValidateProperty(property);
RaisePropertyChanged(nameof(Error));
HasErrors = !string.IsNullOrEmpty(Error);
return Error;
}
}
public string Error
{
get { return _ErrorMessage; }
}
public event PropertyChangedEventHandler PropertyChanged;
private void SaveAction(object obj)
{
if (Model != null && Model.Id == 0)
{
App.EntityManager.Add(Model);
}
App.EntityManager.Save();
}
protected virtual string ValidateProperty(string property)
{
return string.Empty;
}
protected void RaisePropertyChanged(string property)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
public abstract class ViewModel<T> : ViewModel where T : Model
{
protected ViewModel(T model)
{
Model = model;
base.Model = model;
}
public new T Model { get; }
public long Id => Model.Id;
}
XAML:
<Label Content="{StaticResource NameString}" />
<TextBox Text="{Binding Path=Name, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{StaticResource IpString}" />
<TextBox Text="{Binding Path=Ip,ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{StaticResource MacString}" />
<TextBox Text="{Binding Path=Mac, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{StaticResource BroadcastIpString}" />
<TextBox Text="{Binding Path=BroadcastIp, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<Label Content="{StaticResource RoomString}" />
<ComboBox ItemsSource="{Binding Path=Rooms}" SelectedItem="{Binding Path=Room, ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}" />
<GridSplitter Height="25" />
<Button x:Name="SaveButton"
HorizontalAlignment="Right"
Command="{Binding Path=SaveCommand}"
Content="{StaticResource SaveIcon}"
IsEnabled="{Binding Path=CanSave,
Converter={StaticResource TrueToFalseConverter},
UpdateSourceTrigger=PropertyChanged}" />
Calling code in class that implements ICommand interface:
var viewModel = parameter as ComputerViewModel;
_Editor = new ComputerEditor();
_Editor.CloseButtonCommand = new RelayCommand(CloseCommand);
_Editor.SaveButton.Click += (s, e) =>
{
App.EntityManager.Add(_Editor.ComputerEditViewModel.Model);
App.EntityManager.Save();
_Editor.IsOpen = false;
(Application.Current.MainWindow.Content as Grid).Effect = null;
};
if (viewModel == null)
{
_Editor.DataContext = new ComputerEditViewModel(new Computer());
_Editor.Title = Application.Current.FindResource("ComputerAddString").ToString();
}
else
{
_Editor.DataContext = new ComputerEditViewModel(viewModel.Model);
_Editor.Title = Application.Current.FindResource("ComputerEditString").ToString();
}
OpenChildWindow(_Editor);
My problem:
When i create a new entity without any initial values the IDataErrorInfo is executed all the time but the error (red border and label) is only shown when the new entity properties has valid initial values.
Control images
The (1) is the initial controlstate. The first textbox ('Name') has a default value that comes from the entity contructor. All other values (Textboxes) are just empty.
At this point my validation is working in my viewmodel for all textboxes/properties but only the first textbox get the red border and label when the validation fails, cause of the valid start value!
For the other properties i have to set a valid (initial) value before the red border and label is shown (when validation fails, cause of property change) although i check if the textbox/property is empty.
As i said, the validation is working in the viewmodel all the time but the view only shows the red border and label when the initial value is valid against my implementation.
Hoping this question is not to weird.
Feel free to ask anything if something is just unclear
Best regards
Dustin

XAML nested template binding

I have a list view where I bind multiple data templates to using a DataTemplateSelector. However, I cannot build my project, I'm getting an error of "Object reference not set to an instance of an object". I narrowed down the issue to the data binding ItemsSource of the combobox. If I comment out the combobox, my project will build. As I understand, the Binding keyword evaluates at runtime, but this is a compile time error. I tried to get around the error by swapping out to x:Bind, as that evaluates at compile-time but then that required the type of the DataTemplate to be defined.
x:DataType={x:Type templates:FilterDropdownDataTemplate}
However, x:Type isn't defined in a Windows 10 universal app. Any suggestions?
Here is my XAML:
<Page.Resources>
<DataTemplate x:Name="DateComboboxTemplate">
<TextBlock Text="{Binding}"/>
</DataTemplate>
<DataTemplate x:Name="FilterDropdownDataTemplate">
<StackPanel>
<TextBlock Text="{Binding Value}"/>
<ComboBox ItemsSource="{Binding DateRanges}"
SelectionChanged="{Binding DateSelection}"
SelectedItem="{Binding SelectedDateRange, Mode=TwoWay}"
ItemTemplate="{StaticResource DateComboboxTemplate}">
</ComboBox>
</StackPanel>
</DataTemplate>
<config:MainFilterTemplateSelector
x:Name="MainFilterSelector"
FilterDropdownTemplate="{StaticResource FilterDropdownDataTemplate}"
/>
</Page.Resources>
<ListView x:Name="FilterCategories"
Margin="0"
Padding="0"
BorderThickness="0"
ItemsSource="{Binding Filters}"
SelectedItem="{Binding SelectedFilterCategory, Mode=TwoWay}"
IsItemClickEnabled="True"
SelectionChanged="{x:Bind ViewModel.OpenSubFilters}"
ItemTemplateSelector="{StaticResource MainFilterSelector}">
</ListView>
And here is the relevant C# code (I'm using a MVVM pattern):
public class MainFilterViewDropdownListTemplate : Filter
{
private ObservableCollection<string> _dateRanges;
private string _selectedDateRange;
public MainFilterViewDropdownListTemplate() : base()
{
_dateRanges = new ObservableCollection<string>();
}
public ObservableCollection<string> DateRanges
{
get
{
return _dateRanges;
}
set
{
SetProperty(ref _dateRanges, value);
// hard coding these 4 lines for testing for now
_dateRanges.Add("Last 7 days");
_dateRanges.Add("Last 14 days");
_dateRanges.Add("Last 30 days");
_dateRanges.Add("Custom");
}
}
public string SelectedDateRange
{
get
{
return _selectedDateRange;
}
set
{
SetProperty(ref _selectedDateRange, value);
}
}
public IEnumerable<Filter> AllFilters { get; set; }
public void InitializeFields(Filter filter)
{
Column = filter.Column;
DisplayType = filter.DisplayType;
ID = filter.ID;
IsSelected = filter.IsSelected;
ParentId = filter.ParentId;
SelectedCount = filter.SelectedCount;
TotalCount = filter.TotalCount;
Value = filter.Value;
visibility = filter.visibility;
}
private void DateSelection()
{
}
}
And
public class MainFilterTemplateSelector : DataTemplateSelector
{
public DataTemplate FilterDropdownTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object selector)
{
if (selector == null)
{
throw new ArgumentNullException("Template is null");
}
if (!(selector is FilterBase))
{
throw new ArgumentException("This list can only be populated by a class that extends Filter.");
}
else
{
var filterType = selector as Filter;
switch (filterType.DisplayType)
{
case "date":
return FilterDropdownTemplate;
default:
return base.SelectTemplateCore(selector);
}
}
}
}
And
public class Filter : FilterBase
{
private int _selectedCount;
private int _totalCount;
private Visibility _visibility;
public IEnumerable<Filter> Children
{
get;
set;
}
public int TotalCount
{
get
{
return _totalCount;
}
set
{
SetProperty(ref _totalCount, value);
}
}
public int SelectedCount
{
get
{
return _selectedCount;
}
set
{
SetProperty(ref _selectedCount, value);
}
}
public Visibility visibility
{
get
{
return _visibility;
}
set
{
SetProperty(ref _visibility, value);
}
}
public void InitializeAllChildren(IEnumerable<Filter> allFilters)
{
foreach (Filter item in allFilters)
{
item.Children = allFilters.GetAllChildrenFiltersForParentID(item.ID) as IEnumerable<Filter>;
if (item.Children == null)
{
item.TotalCount = 0;
}
else
{
item.TotalCount = item.Children.Count();
item.SelectedCount = item.Children.Where(t => t.IsSelected.Value).Count();
}
}
Children = allFilters.GetAllChildrenFiltersForParentID(ID);
}
}
And
public class FilterBase : ViewModelBase
{
public int ID
{
get
{
return _id;
}
set
{
SetProperty(ref _id, value);
}
}
public string Value
{
get
{
return _value;
}
set
{
SetProperty(ref _value, value);
}
}
public string Column
{
get
{
return _column;
}
set
{
SetProperty(ref _column, value);
}
}
public int ParentId
{
get
{
return _parentId;
}
set
{
SetProperty(ref _parentId, value);
}
}
public string DisplayType
{
get
{
return _displayType;
}
set
{
SetProperty(ref _displayType, value);
}
}
public bool? IsSelected
{
get
{
return _isSelected;
}
set
{
SetProperty(ref _isSelected, value);
}
}
private int _id;
private string _value;
private string _column;
private int _parentId;
private string _displayType;
private bool? _isSelected;
}
And (BindableBase is from the Prism.Mvvm namespace)
public class ViewModelBase : BindableBase, IDisposable
{
PropertyChangeActionHelper _propertyChangeActionHelper;
protected void RegisterPropertyChangeAction(Action action, params string[] monitoredProperties)
{
if (_propertyChangeActionHelper == null)
{
_propertyChangeActionHelper = new PropertyChangeActionHelper(this);
}
_propertyChangeActionHelper.RegisterPropertyChangeAction(action, monitoredProperties);
}
#region IDisposable Support
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_propertyChangeActionHelper != null)
{
_propertyChangeActionHelper.Dispose();
_propertyChangeActionHelper = null;
}
}
}
~ViewModelBase()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
Assuming that the templates namespace is declared and FilterDropdownDataTemplate is a type within that namespace, you should be able to define the DataTemplate's data type without x:Type using the following syntax:
<DataTemplate x:DataType="templates:FilterDropdownDataTemplate">

TextBox will not display the contents of a bound static generic list item

In WPF, I have a static "Customer" object in the definition for MainWindow.xaml.cs. This customer has a publicly accessible string Name property. In expression blend 4, I click on the "Advanced Options" box beside the "Text" property for the TextBox that I would like to bind to the customer name. I then click "Data Binding..." -> "Element Property" -> "window" under "scene elements" -> click the expander arrow beside "ActiveCustomer" -> then click "Name" -> "OK". The binding is to a readonly TextBox, so One Way binding is acceptable as the default. But when I run my app, it doesn't display the customer's name. Any Suggestions?
<TextBox x:Name="AIAHNameTextBox" Height="26" Canvas.Left="90" TextWrapping="Wrap" Canvas.Top="8" Width="100" IsReadOnly="True" VerticalContentAlignment="Center" Text="{Binding ActiveCustomer.Name, ElementName=window, Mode=OneWay}" />
ActiveCustomer is an instance of my Customer class:
namespace WPFBankingSystem
{
public enum CustomerStatus
{ Open, Closed }
public enum TransferType
{ CheckingToSaving, SavingToChecking }
[Serializable]
public class Customer
{
private string address;
private Checking chkAcc;
private string name;
private int pin;
private Saving savAcc;
private string ssn;
private AccountStatus status;
private string tel;
public string Address
{
get { return address; }
set { address = value; }
}
public Checking ChkAcc
{
get { return chkAcc; }
set { chkAcc = value; }
}
public string Name
{ get { return name; } }
public int Pin
{
get { return pin; }
set { pin = value; }
}
public Saving SavAcc
{
get { return savAcc; }
set { savAcc = value; }
}
public string Ssn
{ get { return ssn; } }
public AccountStatus Status
{
get { return status; }
set { status = value; }
}
public string Tel
{
get { return tel; }
set { tel = value; }
}
public void create(string Name, string Address, string TelephoneNumber, string SSN, int PIN)
{
this.address = Address;
this.name = Name;
this.pin = PIN;
this.ssn = SSN;
this.status = AccountStatus.Open;
this.tel = TelephoneNumber;
}
public void delete()
{
if (this.chkAcc != null)
{ chkAcc.close(); }
if (this.savAcc != null)
{ savAcc.close(); }
}
public bool hasChkAcc()
{ return (this.chkAcc != null) ? true : false; }
public bool hasSavAcc()
{ return (this.savAcc != null) ? true : false; }
public void show()
{ }
public void transfer(double Amount, TransferType Type)
{
if(this.hasChkAcc() && this.hasSavAcc())
{
switch(Type)
{
case TransferType.CheckingToSaving:
this.chkAcc.Balance -= Amount;
this.savAcc.Balance += Amount;
break;
case TransferType.SavingToChecking:
this.savAcc.Balance -= Amount;
this.chkAcc.Balance += Amount;
break;
}
}
else
{ throw new Exception("You do not have both a checking account and a saving account."); }
}
public Customer()
{ }
~Customer()
{ this.delete(); }
}
}
Inside MainWindow.xaml.cs, the customer is defined just as a public Customer object:
public Customer ActiveCustomer
{ get; set; }
You cannot bind to static properties like you can to instance properties. The property ActiveCustomer then does not exist on the element named window it exists in the class MainWindow. You should be able to fix the binding by using a Source in conjunction with x:Static:
{Binding Name, Source={x:Static local:MainWindow.ActiveCustomer}}
Note that x:Static has a very specific syntax, it does not allow an arbitrary path or the like.
Even if the binding works this is problematic though as you cannot implement INPC for static properties, so if you assign a new object to ActiveCustomer there will be no update.

With linked ComboBoxes, secondary combobox always starts empty

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.

Categories

Resources