/// <summary> /// Initializes a new instance of the <see cref="T:TabViewModel"/> class. /// </summary> public TabViewModel(MainViewModel mainViewModel) { if (mainViewModel == null) { throw new ArgumentNullException("mainViewModel"); } this.MainViewModel = mainViewModel; React.To(() => mainViewModel.ActiveTab == this) .Set(() => IsActive); React.To(() => IsActive) .Switch(true, Brushes.Orange, Brushes.Gray) .Set(() => HeaderBackgroundColor); React.To(() => IsActive ? Header + " [active]" : Header) .Set(() => ExtendedHeader); //TODO: allow tracked expressions in switch method //(maybe make another method - ReactiveSwitch not to confuse). //Most of the time reactive behaviour would be expected, though. //React.To(() => IsActive) // .Switch(true, () => Header + " [active]", () => Header) // .Set(() => ExtendedHeader); }
public void TrackedCollectionOfCollections_DoesNotPopulateInnerCollectionItemChanges() { CollectionOfCollectionsObject = new CollectionOfCollections(); var inner = new ObservableCollection <Person>(); int age = -1; CollectionOfCollectionsObject.DeepCollection.Add(inner); React.To(() => CollectionOfCollectionsObject.DeepCollection .TrackItems().First().FirstOrDefault()) .Where(p => p != null).Set(p => age = p.Age); var person = new Person() { Age = 10 }; inner.Add(person); age.Should().Be(10, "as person has been added to the inner collection, its Count has changed. " + "Expression should be reevaluated."); person.Age = 20; age.Should().Be(10, "person is located in the inner collection and property changes of " + "individual (inner) items should not be tracked."); }
/// <summary> /// Initializes a new instance of the <see cref="T:PlaceholderTab"/> class. /// </summary> public PlaceholderTab(MainViewModel mainViewModel) : base(mainViewModel) { //Autonumbering of placeholder tabs in format "Placeholder 1/4", etc. int currentCount = mainViewModel.Tabs.Count(tab => tab is PlaceholderTab) + 1; React.To(() => mainViewModel.Tabs.Count(tab => tab is PlaceholderTab)) .Set(totalCount => this.Header = string.Format("Placeholder {0}/{1}", currentCount, totalCount)); }
static Settings() { current = new Settings(); var local = current; local.DecimalPlaces = 1; React.To(() => current.DecimalPlaces) .Set(places => local.NumberFormat = string.Format("{{0:f{0}}}", places)); }
/// <summary> /// Initializes a new instance of the <see cref="T:PeopleViewModel"/> class. /// </summary> public PeopleViewModel(MainViewModel mainViewModel) : base(mainViewModel) { this.Header = "People"; this.AddPersonCommand = new RelayCommand(AddPerson); actors = new ObservableCollection <PersonViewModel>(); actors.Add(new PersonViewModel(this) { Age = 54, Name = "Kevin Spacey" }); actors.Add(new PersonViewModel(this) { Age = 32, Name = "Joseph Gordon-Levitt" }); actors.Add(new PersonViewModel(this) { Age = 61, Name = "Mickey Rourke" }); filmDirectors = new ObservableCollection <PersonViewModel>(); filmDirectors.Add(new PersonViewModel(this) { Age = 54, Name = "Frank Darabont" }); filmDirectors.Add(new PersonViewModel(this) { Age = 52, Name = "Peter Jackson" }); filmDirectors.Add(new PersonViewModel(this) { Age = 50, Name = "Quentin Tarantino" }); React.To(() => IsViewingActors ? actors : filmDirectors) .Set(() => People); React.To(() => People.TrackItems(p => p.Age)) .Where(people => people.Any()) .Select(people => people.Average(p => p.Age)) .SetAndNotify(() => AverageAge); var settings = Settings.Current; React.To(() => string.Format("Average age:" + settings.NumberFormat, AverageAge)) .SetAndNotify(() => AverageAgeString); }
public void TrackedCollection_RaisesNotificationsForIndividualItems() { People = new ObservableCollection <Person>(); int age = -1; React.To(() => People.TrackItems()) .Where(c => c.Any()) .Set(c => age = c.First().Age); var person = new Person() { Age = 20 }; People.Add(person); person.Age = 30; age.Should().Be(30, "age has been changed and items ought to be tracked"); }
/// <summary> /// Initializes a new instance of the <see cref="T:MainWindowVM"/> class. /// </summary> public MainWindowVM() { this.Logger = new InMemoryLogger(); OperationPanelVM adultPanel = new AdultPanelVM(this.Logger); OperationPanelVM youngsterPanel = new YoungsterPanelVM(this.Logger); personProperty = this.Create(() => Person, new Person()); React.To(() => 18 - Person.Age).Where(age => age > 0).Set(age => YearsBelow18 = age); React.To(() => 70 - Person.Age).SetAndNotify(() => YearsLeftToRetirement); //One can use Select() to convert the value stream and then call SetAndNotify() //with the target property as an argument. Thus, still no need for manual INPC event raising. //React.To(() => Person.Age >= 18).Select(isAdult => isAdult ? adultPanel : youngsterPanel). // SetAndNotify(() => OperationPanel); //The same result can be obtained by using the Switch extension method. React.To(() => Person.Age).Switch(age => age >= 18, adultPanel, youngsterPanel). SetAndNotify(() => OperationPanel); }
public CyclicAccess_InnerModel(CyclicAccess_OuterModel outerModel) { this.OuterModel = outerModel; React.To(() => this.Age - OuterModel.AverageAge) .Select(diff => { if (diff > 0) { return(new AnyReferenceType(-90.0)); } else if (diff == 0) { return(new AnyReferenceType(0.0)); } else { return(new AnyReferenceType(90.0)); } }) .Set(() => ArrowIndicatorRotation); }
public NotificationsSwallowed_InnerModel(NotificationsSwallowed_OuterModel outerModel) { this.OuterModel = outerModel; React.To(() => this.Age - OuterModel.AverageAge) .Select(diff => { if (diff > 0) { return(new AnyReferenceType(-90.0)); } else if (diff == 0) { return(new AnyReferenceType(0.0)); } else { return(new AnyReferenceType(90.0)); } }) .SetAndNotify(() => ArrowIndicatorRotation); }
public CyclicAccess_OuterModel() { actors = new ObservableCollection <CyclicAccess_InnerModel>(); actors.Add(new CyclicAccess_InnerModel(this) { Age = 54 }); actors.Add(new CyclicAccess_InnerModel(this) { Age = 32, }); actors.Add(new CyclicAccess_InnerModel(this) { Age = 61 }); filmDirectors = new ObservableCollection <CyclicAccess_InnerModel>(); filmDirectors.Add(new CyclicAccess_InnerModel(this) { Age = 54 }); filmDirectors.Add(new CyclicAccess_InnerModel(this) { Age = 52 }); filmDirectors.Add(new CyclicAccess_InnerModel(this) { Age = 50 }); React.To(() => IsViewingActors ? actors : filmDirectors) .Set(() => People); React.To(() => People.TrackItems()) .Where(people => people.Any()) .Select(people => people.Average(p => p.Age)) .SetAndNotify(() => AverageAge); }
public void NonTrackedCollectionOfCollections_DoesNotPopulateEvenOuterCollectionItemChanges() { CollectionOfCollectionsObject = new CollectionOfCollections(); var inner = new ObservableCollection <Person>(); int age = -1; CollectionOfCollectionsObject.DeepCollection.Add(inner); React.To(() => CollectionOfCollectionsObject.DeepCollection.First().FirstOrDefault()). Where(p => p != null).Set(p => age = p.Age); var person = new Person() { Age = 10 }; inner.Add(person); age.Should().Be(-1, "item tracking is off. Even items of the outer collection " + "should not be listened to."); person.Age = 20; age.Should().Be(-1, "item tracking is off"); }
public PersonViewModel(PeopleViewModel peopleViewModel) { if (peopleViewModel == null) { throw new ArgumentNullException("peopleViewModel"); } this.PeopleViewModel = peopleViewModel; React.To(() => this.Age - PeopleViewModel.AverageAge) .Select(diff => { if (diff > 0) { return("above average"); } else if (diff == 0) { return("exact average"); } else { return("below average"); } }) .SetAndNotify(() => ComparedToAverageAge); //TODO: SetAndNotify usually has no equality check on the new value. //Put such logic in SetAndNotify itself. React.To(() => this.Age - PeopleViewModel.AverageAge) .Select(diff => { if (diff > 0) { return(new RotateTransform(-90.0)); } else if (diff == 0) { return(new RotateTransform(0.0)); } else { return(new RotateTransform(90.0)); } }) .SetAndNotify(() => ArrowIndicatorRotation); React.To(() => this.Age - PeopleViewModel.AverageAge) .Select(diff => { if (diff > 0) { return(Brushes.Green); } else if (diff == 0) { return(Brushes.Blue); } else { return(Brushes.Red); } }) .SetAndNotify(() => ArrowIndicatorColor); }