Making a dynamic set of 3 pickers on Xamarin.Forms - c#

we are developing a cross platform app on Xamarin.Forms.
On one of the pages we need to display a set of 3 pickers with the same list of items. The idea is that when you select an item on one of the pickers it gets removed from the item-source of the other two.
To do this we developed the following code:
We started with a list of Items called BaseList which we get from a web service. We also create 3 separate lists (ListA, ListB and ListC) and 3 Items to store the selected Items of each picker (SelectedA, SelectedB and SelectedC).
private List<Item> BaseList;
private List<Item> _ListA;
private Item _SelectedA;
private List<Item> _ListB;
private Item _SelectedB;
private List<Item> _ListC;
private Item _SelectedC;
…
//Api Calls
private void LoadData()
{
…
BaseList = new List<Item> (ListFromWebServices);
_ListA = new List<Item>(BaseList);
OnPropertyChanged(nameof(ListA));
_ListB = new List<Item>(BaseList);
OnPropertyChanged(nameof(ListB));
_ListC = new List<Item>(BaseList);
OnPropertyChanged(nameof(ListC));
}
…
//Public Fields
public List<Item> ListA
{
get
{
return _ListA;
}
}
public Item SelectedA
{
get
{
return _SelectedA;
}
set
{
SetProperty(ref _SelectedA, value, nameof(SelectedA));
}
}
public List<Item> ListB
{
get
{
return _ListB;
}
}
public Item SelectedB
{
get
{
return _SelectedB;
}
set
{
SetProperty(ref _SelectedB, value, nameof(SelectedB));
}
}
public List<Item> ListC
{
get
{
return _ListC;
}
}
public Item SelectedC
{
get
{
return _SelectedC;
}
set
{
SetProperty(ref _SelectedC, value, nameof(SelectedC));
}
}
This code is on our ViewModel, so we use SetProperty to set the referenced property to the value and invoke PropertyChangedEventArgs from INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value,
[CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
In order to update the ItemSource's, whenever a selected item is changed we call OnSelectedItemChanged from the setters of SelectedA, SelectedB and SelectedC. This method receives an index which indicates which Picker triggered it:
private void OnSelectedItemChanged(int index)
{
Item CurrentA = SelectedA;
Item CurrentB = SelectedB;
Item CurrentC = SelectedC;
int i;
switch (index)
{
case 0:
_ListB = new List<Item> (BaseList);
_ListB.Remove(CurrentA);
_ListB.Remove(CurrentC);
OnPropertyChanged(nameof(ListB));
_ListC = new List<Item>(BaseList);
_ListC.Remove(CurrentA);
_ListC.Remove(CurrentB);
OnPropertyChanged(nameof(ListC));
i = ListB.IndexOf(CurrentB);
if (i > -1)
{
_SelectedB = ListB[i];
}
OnPropertyChanged(nameof(SelectedB));
i = ListC.IndexOf(CurrentC);
if (i > -1)
{
_SelectedC = ListC[i];
}
OnPropertyChanged(nameof(SelectedC));
break;
case 1:
_ListA = new List<Item>(BaseList);
_ListA.Remove(CurrentB);
_ListA.Remove(CurrentC);
OnPropertyChanged(nameof(ListA));
_ListC = new List<Item>(BaseList);
_ListC.Remove(CurrentA);
_ListC.Remove(CurrentB);
OnPropertyChanged(nameof(ListC));
i = ListA.IndexOf(CurrentA);
if (i > -1)
{
_SelectedA = ListA[i];
}
OnPropertyChanged(nameof(SelectedA));
i = ListC.IndexOf(CurrentC);
if (i > -1)
{
_SelectedC = ListC[i];
}
OnPropertyChanged(nameof(SelectedC));
break;
case 2:
_ListA = new List<Item>(BaseList);
_ListA.Remove(CurrentB);
_ListA.Remove(CurrentC);
OnPropertyChanged(nameof(ListA));
_ListB = new List<Item>(BaseList);
_ListB.Remove(CurrentA);
_ListB.Remove(CurrentC);
OnPropertyChanged(nameof(ListB));
i = ListA.IndexOf(CurrentA);
if (i > -1)
{
_SelectedA = ListA[i];
}
OnPropertyChanged(nameof(SelectedA));
i = ListB.IndexOf(CurrentB);
if (i > -1)
{
_SelectedB = ListB[i];
}
OnPropertyChanged(nameof(SelectedB));
break;
}
}
What we do here is basically save the current selected item for each picker on a separate variable, copy the BaseList into the two pickers that didn't call the event, then on the each new list remove all the options in use by the other pickers, set again the selected Item on each new list to the one that was selected originally and finally call OnPropertyChanged() to inform the views of the change.
The issue here is that when we change the ItemSource on a Picker it sets the SelectedItem to null. calling OnPropertyChanged() on the setter after OnSelectedItemChanged()was called leads to an infinite loop of one Picker updating the other, and adding a filter that checks if the value isn't null before setting it makes the Picker display no selected item, while the value is already set.

just in case anyone has the same issue, we found a solution for this. Turns out if you make CurrentA, CurrentB and CurrentC global variables and add on each case an if ((CurrentA != SelectedA) && (!(SelectedA is null))) { ... (do all the stuff) } break; and at the end you set
_SelectedA = CurrentA;
OnPropertyChanged(nameof(SelectedA));
_SelectedB = CurrentB;
OnPropertyChanged(nameof(SelectedB));
_SelectedC = CurrentC;
OnPropertyChanged(nameof(SelectedC));
it works. We don't know why tho :)

Related

Be able to show the next value in a Linked List by clicking a button

This is probably a simple task however I am unable to solve.
So currently I have set up a form which contains a textbox and a button and I want to be able to click the button and the first value within the LinkedList will show up in the textbox. If I click the button again then the next value will show up etc.
I currently go it so that the first value will show up but then I am unable to proceed to the next value.
This is the code I have currently:
public class Node
{
public string data;
public Node next;
public Node(string newData)
{
data = newData;
next = null;
}
public void AddEnd(string data)
{
if (next == null)
{
next = new Node(data);
}
else
{
next.AddEnd(data);
}
}
}
public class myList
{
public void AddEnd(string data)
{
if (headnode == null)
{
headnode = new Node(data);
}
else
{
headnode.AddEnd(data);
}
}
public string getFirst() // this gets the first value within the list and returns it
{
if (headnode == null)
{
throw new Exception("List is empty");
}
Node node = headnode;
while (node.next != null)
{
node = node.next;
}
return node.data;
}
I also tried using this:
public class NavigationList<T> : List<T>
{
private int _currentIndex = -1;
public int CurrentIndex
{
get
{
if (_currentIndex == Count)
_currentIndex = 0;
else if (_currentIndex > Count - 1)
_currentIndex = Count - 1;
else if (_currentIndex < 0)
_currentIndex = 0;
return _currentIndex;
}
set { _currentIndex = value; }
}
public T MoveNext
{
get { _currentIndex++; return this[CurrentIndex]; }
}
public T Current
{
get { return this[CurrentIndex]; }
}
}
However, I am not really familiar with something like this so I wasn't sure on how to use it.
So you have a sequence of items, and the only thing that you want, is to get the first item, and once you've got an item, every time your ask for it, you want the next item, until there are no more items left.
In .NET this is called an IEnumerable, or if you know what kind of items are in your sequence, for instance items of MyClass, it is called an IEnumerable<MyClass>. In your case you need an IEnumerable<string>.
Luckily .NET is loaded with classes that implement IEnumerable. Two of the most used ones are array and list. You seldom have to create an enumerable class yourself, re-use the existing ones and enumerate over it.
List<string> myData = ... // fill this list somehow.
IEnumerator<string> myEnumerator = null // we are not enumerating yet.
string GetNextItemToDisplay()
{ // returns null if there are no more items to display
// if we haven't started yet, get the enumerator:
if (this.myEnumerator == null) this.myEnumerator = this.myData.GetEnumerator();
// get the next element (or if we haven't fetched anything yet: get the first element
// for this we use MoveNext. This returns false if there is no next element
while (this.myEnumerator.MoveNext())
{
// There is a next string. It is in Current:
string nextString = enumerator.Current();
return nextString;
}
// if here: no strings left. return null:
return null;
}
This looks like a lot of code, but if you remove the comments it is in fact just a few lines of code:
string GetNextItemToDisplay()
{
if (this.myEnumerator == null) this.myEnumerator = this.myData.GetEnumerator();
while (this.myEnumerator.MoveNext())
return enumerator.Current();
return null;
}
Your ButtonClick event handler:
void OnButtonClick(object sender, eventArgs e)
{
string nextItemToDisplay = this.GetNextItemToDisplay();
if (nextItemToDisplay != null)
this.Display(nextItemToDisplay);
else
this.DisplayNoMoreItems():
}
If you want to start over again with the first element, for instance after changing the List
void RestartEnumeration()
{
this.myEnumerator = null;
}

Xamarin forms set Picker SelectedItem

I am working with a xamarin Forms.
I am using Picker for DropDownList.
How can I set selectedItem to Picker?
My code
<Picker x:Name="VendorName" Title="Select" ItemDisplayBinding="{Binding VendorName}" SelectedItem="{Binding VendorName}" Style="{StaticResource PickerStyle}"></Picker>
and server side code is
Device.BeginInvokeOnMainThread(() =>
{
VendorName.ItemsSource = VendorList;
});
var currentVendor = new List<Vendor>();
currentVendor.Add(new Vendor { VendorID = "111", VendorName = "aaaa" });
VendorName.SelectedItem = currentVendor;
This may not be the most efficient but you could loop to find the index and set that way.
for (int x = 0; x < VendorList.Count; x++)
{
if (VendorList[x].VendorName == currentVendor .VendorName )
{
VendorName.SelectedIndex = x;
}
}
After adding all values as list in Picker
just treat with it as an array
so if you want to set selected item just set selected item index
currentVendor.SelectedIndex = 0;
zero means you make selected item is the first one you added to Picker
If you are using MVVM, and want to set SelectedItem from the view model, things get tricky. There seems to be a bug in Xamarin that prevents us from using SelectedItem with a two way binding. More info: Xamarin Forms ListView SelectedItem Binding Issue and https://xamarin.github.io/bugzilla-archives/58/58451/bug.html.
Luckily, we can easily write our own Picker.
public class TwoWayPicker : Picker
{
public TwoWayPicker()
{
SelectedIndexChanged += (sender, e) => SelectedItem = ItemsSource[SelectedIndex];
}
public static new readonly BindableProperty SelectedItemProperty = BindableProperty.Create(
nameof(SelectedItem), typeof(object), typeof(TwoWayPicker), null, BindingMode.TwoWay, propertyChanged: OnSelectedItemChanged);
public new object SelectedItem
{
get => GetValue(SelectedItemProperty);
set => SetValue(SelectedItemProperty, value);
}
private static void OnSelectedItemChanged(BindableObject bindable, object oldValue, object newValue)
{
var control = (TwoWayPicker)bindable;
control.SetNewValue(newValue);
}
private void SetNewValue(object newValue)
{
if (newValue == null)
{
return;
}
for(int i = 0; i < ItemsSource.Count; i++)
{
if (ItemsSource[i].Equals(newValue))
{
SelectedIndex = i;
return;
}
}
}
}
Because is uses the same SelectedItem property, it is a drop-in replacement for Picker.
Note that if you want value equality rather than reference equality for the item class, you'll also need to override Equals like this:
public override bool Equals(object obj)
{
var other = obj as YourClass;
if (other == null)
{
return false;
}
else
{
return other.SomeValue == SomeValue; // implement your own
}
}
If you define the item class as a record instead of a class then it can select the item programmatically using the SelectedItem property.
In your case change
public class Vendor { // your class properties }
to
public record Vendor { // your class properties }
This will now work
VendorName.SelectedItem = currentVendor;

Filter a property by the value of another property

I have two drop down lists. Niether of them have a relation ship with each other. But I need to filter one drop down list based on the chosen value of another drop down list.
I can filter it in code. When I debug I can see the filtered results on the property. However when I run the app, it does not work. Here is my code so far:
private BindingList<Commodity> _AllocationCommodities;
[Browsable(false)]
public BindingList<Commodity> AllocationCommodities
{
get
{
if (_AllocationCommodities == null)
{
_AllocationCommodities = new BindingList<Commodity>();
ChangeCommodities();
}
return _AllocationCommodities;
}
}
private SourceEntity _SourceEntity;
[ImmediatePostData]
[Association("SourceEntity-LimitAllocations")]
[RuleRequiredField("RuleRequiredField_LimitAllocation_SourceEntity", DefaultContexts.Save)]
public SourceEntity SourceEntity
{
get
{
return _SourceEntity;
}
set
{
//New Code
if (SetPropertyValue<SourceEntity>("SourceEntity", value))
{
if (IsSaving || IsLoading) return;
ChangeCommodities();
}
}
}
private Commodity _Commodity;// This is the drop down to be filtered
[ImmediatePostData]
[DataSourceProperty("AllocationCommodities")] //// This Attribute Should filter Commodities
[RuleRequiredField("RuleRequiredField_LimitAllocation_Commodity", DefaultContexts.Save)]
public Commodity Commodity
{
get
{
return _Commodity;
}
set
{
SetPropertyValue("Commodity", ref _Commodity, value);
if (Commodity.Oid != Guid.Empty)
AllocationVolumeUnits.Reload();
}
}
private void ChangeCommodities()
{
if (!this.IsLoading && _SourceEntity != null)
{
_AllocationCommodities.RaiseListChangedEvents = false;
_AllocationCommodities.Clear();
OperandValue[] _params;
System.Collections.Generic.List<CMSBOD.SourceCommodity> _sc = new System.Collections.Generic.List<SourceCommodity>();
BindingList<Commodity> _Commodities = new BindingList<Commodity>();
foreach (SourceCommodityEntity _tempSCE in _SourceEntity.SourceCommodityEntities)
{
if (_tempSCE.SourceCommodity != null)
_sc.Add(_tempSCE.SourceCommodity);
}
foreach (SourceCommodity _tempSC in _sc)
{
if (_tempSC.Commodity != null && !_Commodities.Contains<Commodity>(_tempSC.Commodity) && _tempSC.Commodity.IsActive)
_Commodities.Add(_tempSC.Commodity);
}
_AllocationCommodities.RaiseListChangedEvents = true;
_AllocationCommodities = _Commodities;///This is where I can see the filtered list when debugging.
}
}
You can find a DataSourceCriteria useful in this scenario, instead of DataSourceProperty.
Assuming you have collection properties that associates Commodity back to SourceCommodityEntity, you can use this criteria:
[DataSourceCriteria("IsActive And SourceCommodities[SourceCommodityEntities[SourceEntity = '#SourceEntity'] ]")]
Even if its designed to be a 1x1 assocation, you can find that associations can be useful for filtering purposes.

ObservableCollection filter Selected Item

I have a problem that I don't know how to solve.
I have a observable collection that I filter the items as I type in a textbox the problem is that when I select the filtered item I get the wrong selected index.
For example I have one item after filtering the real selected index is 2 but because it sets the collection as I type it set the index to one if the only filtered item left is one.
So how do I get the right item selected. Like in the mail application to make my question maybe easier to understand
Here is the selection changed event:
private void searchToDoItemsListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (searchToDoItemsListBox.SelectedIndex == -1)
return;
NavigationService.Navigate(new Uri("/DetailsPage.xaml?selectedItemSearch=" + searchToDoItemsListBox.SelectedIndex, UriKind.Relative));
searchToDoItemsListBox.SelectedIndex = -1;
}
And here is for the details page:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (NavigationContext.QueryString.TryGetValue("selectedItemSearch", out selectedIndexSearch))
{
int indexSearch = int.Parse(selectedIndexSearch);
DataContext = App.ViewModel.AllToDoItems[indexSearch];
}
}
Bind to the SelectedItem
<ListBox SelectedItem="{Binding Selected, Mode=TwoWay}" ItemsSource="Binding={Items}">
</ListBox>
and you have to fields:
public ObservableCollection<ItemType> Items {get;set;} //setted while filtering, does it?
and
private ItemType _selected;
public ItemType Selected
{
get
{
return _selected;
}
set
{
_selected = value;
//here you can save the item.
//For example save the item id, and navigate to DetailsPage
}
}
And then, you can get the item from list:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (NavigationContext.QueryString.TryGetValue("selectedItemSearch", out selectedIndexSearch))
{
int id = int.Parse(selectedIndexSearch);
DataContext = GetById(id)
}
}
public ItemType GetByIf(id)
{
for(int i = 0; i < App.ViewModel.AllToDoItems.Count; i++)
{
if(App.ViewModel.AllToDoItems[i].Id == id) return App.ViewModel.AllToDoItems[i];
}
return null;
}
Have done like this now and i get nothing now at all. It navigates but nothings shows.
if (NavigationContext.QueryString.TryGetValue("selectedItemSearch", out selectedIndexSearch))
{
//int indexSearch = int.Parse(selectedIndexSearch);
//DataContext = App.ViewModel.AllToDoItems[indexSearch];
int id = int.Parse(selectedIndexSearch);
DataContext = GetById(id);
}
public object GetById(int id)
{
for(int i = 0; i < App.ViewModel.AllToDoItems.Count; i++)
{
if (App.ViewModel.AllToDoItems[i].ToDoItemId == id)
return App.ViewModel.AllToDoItems[i];
}
return null;
}
The AllToDoItems looks like below, its a observable collection;
This is in the ViewModel this below load the collection from the database.
ToDoItem is the table name in the Model.
// Specify the query for all to-do items in the database.
var toDoItemsInDB = from ToDoItem todo in toDoDB.Items
select todo;
// Query the database and load all to-do items.
AllToDoItems = new ObservableCollection<ToDoItem>(toDoItemsInDB);
The Model looks like this:
public Table<ToDoItem> Items;
//public Table<ToDoFavCategory> Categories;
}
[Table]
public class ToDoItem : INotifyPropertyChanged, INotifyPropertyChanging
{
// Define ID: private field, public property, and database column.
private int _toDoItemId;
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int ToDoItemId
{
get { return _toDoItemId; }
set
{
if (_toDoItemId != value)
{
NotifyPropertyChanging("ToDoItemId");
_toDoItemId = value;
NotifyPropertyChanged("ToDoItemId");
}
}
}
Its easier maybe to take a look at this link where i have build it from
http://msdn.microsoft.com/en-us/library/hh286405(v=vs.92).aspx

RaisePropertyChanged not updating UI

I'm having trouble getting my UI to update Two Listboxes' to update properly when my ViewModel changes.
First, the basic logic behind the page:
Movie is an object with a title, and a variety of MovieDetails. Some MovieDetail are different than others, as they are detailed which is a glorified way of saying they're more Important.
I use two ListBoxes to separate these MovieDetails into stacked ListBoxes, one for 'Detailed' and one for 'NotDetailed'
If a movie has no 'Detailed' attributes, the corresponding list is Hidden via a BooleanToVisibilityConverter (and vice-versa)
When I navigate to the page, I set the Movie the page corresponds to, and it should RaisePropertyChanged to alert the AllMoviesDetail ObservableCollection that it should re-get Movies.MovieDetailFetchedList.
From there, AllMoviesDetail would alert the two ObservableCollections (Detailed, NotDetailed) they should be re-get.
In fact, RaisePropertyChanged on NotDetailedMovieDetails or DetailedMovieDetails does not seem to do anything either. (And the corresponding HasNotDetailedMovieDetails, Has...)
What does work, however, is if I add more items into the list, the CollectionChanged event seems to fire and reactivate the list. I have also been able to do this by instantiating the ObservableCollections in code first var temp = DetailedMoviesDetail;
public class MoviesDetailViewModel : ViewModelBase
{
#region Property Names
public const string MoviePropertyString = "Movie";
public const string AllMoviesDetailPropertyString = "AllMoviesDetail";
public const string DetailedMoviesDetailPropertyString = "DetailedMoviesDetail";
public const string NotDetailedMoviesDetailPropertyString = "NotDetailedMoviesDetail";
public const string HasNotDetailedMoviesDetailPropertyString = "HasNotDetailedMoviesDetail";
public const string HasDetailedMoviesDetailPropertyString = "HasDetailedMoviesDetail";
public const string NotDetailedHeaderPropertyString = "NotDetailedHeader";
#endregion
public MoviesDetailViewModel()
{
if (IsInDesignMode)
{
Movie = DesignDataStore.MovieList[0];
Movie.Category = Category.DDA;
}
}
private Movie _Movie;
/// <summary>
/// The Movie for which to browse MoviesDetail. It is expected when setting this property, that MoviesDetail for it have been downloaded previously.
/// </summary>
/// <remarks>The 'Master' property for this ViewModel. All properties are Dependent on this and the underlying property MoviesDetailList</remarks>
/// <seealso cref="MovieDetailFetchedList"/>
public Movie Movie
{
get { return _Movie; }
set
{
if (_Movie != value)
{
if (_Movie != null)
_Movie.MovieDetailFetchedList.CollectionChanged -= MoviesDetailListChanged;
_Movie = value;
RaisePropertyChanged(MoviePropertyString);
RaisePropertyChanged(StatementPeriodAvailablePropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
Movie.MovieDetailFetchedList.CollectionChanged += MoviesDetailListChanged;
RaisePropertyChanged(AllMoviesDetailPropertyString);
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedHeaderPropertyString);
}
}
}
private void MoviesDetailListChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
if (((MovieDetail) item).IsDetailed())
DetailedMoviesDetail.Add(item as MovieDetail);
else
NotDetailedMoviesDetail.Add(item as MovieDetail);
}
}
else
{
RaisePropertyChanged(AllMoviesDetailPropertyString);
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
}
}
#endregion
private MovieDetailFetchedList _allMoviesDetail;
public MovieDetailFetchedList AllMoviesDetail
{
get
{
if (Movie == null)
return new MovieDetailFetchedList();
return _allMoviesDetail ?? (AllMoviesDetail = Movie.MovieDetailFetchedList);
}
set
{
if (_allMoviesDetail != value)
{
if (_allMoviesDetail != null)
_allMoviesDetail.CollectionChanged -= MoviesDetailListChanged;
_allMoviesDetail = value;
_allMoviesDetail.CollectionChanged += MoviesDetailListChanged;
RaisePropertyChanged(AllMoviesDetailPropertyString);
//force update
DetailedMoviesDetail = NotDetailedMoviesDetail = null;
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasDetailedMoviesDetailPropertyString);
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString);
}
}
}
public bool HasNotDetailedMoviesDetail { get { return NotDetailedMoviesDetail != null && NotDetailedMoviesDetail.Count > 0; } }
private ObservableCollection<MovieDetail> _notDetailedMoviesDetail;
public ObservableCollection<MovieDetail> NotDetailedMoviesDetail
{
get
{
if (Movie == null) return new ObservableCollection<MovieDetail>();
return AllMoviesDetail;
return _notDetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter
(NotDetailedMoviesDetail = AllMoviesDetail.Where(mem => !mem.IsDetailed()).ToObservableCollection());
}
set
{
_notDetailedMoviesDetail = value;
RaisePropertyChanged(NotDetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasNotDetailedMoviesDetailPropertyString);
}
}
public bool HasDetailedMoviesDetail
{ get { return DetailedMoviesDetail != null && DetailedMoviesDetail.Count > 0; } }
private ObservableCollection<MovieDetail> _DetailedMoviesDetail;
public ObservableCollection<MovieDetail> DetailedMoviesDetail
{
get
{
if (Movie == null) return new ObservableCollection<MovieDetail>();
return AllMoviesDetail;
return _DetailedMoviesDetail ?? //make sure RaisePropertyChanged happens by using property setter
(DetailedMoviesDetail = AllMoviesDetail.Where(mem => mem.IsDetailed()).ToObservableCollection());
}
set
{
_DetailedMoviesDetail = value;
RaisePropertyChanged(DetailedMoviesDetailPropertyString);
RaisePropertyChanged(HasDetailedMoviesDetailPropertyString);
}
}
private string _DetailedHeader;
public string DetailedHeader
{
get { return _DetailedHeader ?? (_DetailedHeader = AppResources.in_available); }
set { _DetailedHeader = value; }
}
public string NotDetailedHeader
{
get { return (Movie != null && Movie.Category == Category.DRAMA) ? AppResources.Movie_MoviesDetail : AppResources.not_in_available; }
}
}
All of your property getters (except AllMoviesDetail) have two return statements. Since only the first will be executed, the values are not being assigned and the PropertyChanged events are not being twiggered.

Categories

Resources