Handle multiple button views - mvvm

My question is about how to control the background and text color of multiple buttons when you read a button click in MVVM. To make my question a bit clear please have a look at the UI I have attached.
I have already implemented this on code behind i.e on button click, I am handling all of the buttons separately. The original background and text color are white and black respectively and when you click on any other button except 1W that button will be highlighted.
In the next image, 3M is clicked
lbl3M.BackgroundColor = Color.FromHex(defaultColor);
lbl3M.TextColor = Color.White;
if (lbl1M.BackgroundColor != Color.White)
{
lbl1M.BackgroundColor = Color.White;
lbl1M.TextColor = Color.Black;
}
if (lbl1W.BackgroundColor != Color.White)
{
lbl1W.BackgroundColor = Color.White;
lbl1W.TextColor = Color.Black;
}
if (lbl6M.BackgroundColor != Color.White)
{
lbl6M.BackgroundColor = Color.White;
lbl6M.TextColor = Color.Black;
}
if (lbl1Y.BackgroundColor != Color.White)
{
lbl1Y.BackgroundColor = Color.White;
lbl1Y.TextColor = Color.Black;
}
I have done this on each button clicked.
I know this approach is not cost-effective and I want to learn how to implement in MVVM way
EDIT:
I have created a function which reset all the buttons to Original UI and change the UI on button clicked
void ResetButtonUI()
{
lbl1W.BackgroundColor = Color.White;
lbl1W.TextColor = Color.Black;
lbl1M.BackgroundColor = Color.White;
lbl1M.TextColor = Color.Black;
lbl3M.BackgroundColor = Color.White;
lbl3M.TextColor = Color.Black;
lbl6M.BackgroundColor = Color.White;
lbl6M.TextColor = Color.Black;
lbl1Y.BackgroundColor = Color.White;
lbl1Y.TextColor = Color.Black;
}
and on each button i have this logic
ResetButtonUI();
button.BackgroundColor = Color.FromHex(defaultColor);
button.TextColor = Color.White;

Compared with listview, CollectionView is more suitable for your needs. Listview is more complicated to place horizontally.
Here is running GIF.
Here is code.
<CollectionView ItemsSource="{Binding Persons}" HeightRequest="50" SelectionMode="Single" SelectionChanged="CollectionView_SelectionChanged_1" >
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center" >
<Label Text="{Binding FirstName}" FontSize="20" Margin="20,10,20,0"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Background code.
BindingContext = new HomepageViewModel();
public List Persons { get; set; }
public HomepageViewModel() {
Persons = new List<Person>();
Persons.Add(new Person() { FirstName = "1W" });
Persons.Add(new Person() { FirstName = "1M" });
Persons.Add(new Person() { FirstName = "3M" });
Persons.Add(new Person() { FirstName = "6M" });
Persons.Add(new Person() { FirstName = "1Y" });
}
}
If you want to change the selectItem color, here is a link about it.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/collectionview/selection#change-selected-item-color

So there are 5 options and the user have to choose one of them.
The ViewModel must contain 2 properties:
Collection of all options
Selected option
It should look like this
// ReactiveObject is from ReactiveUI => https://reactiveui.net/
public class MainViewModel : ReactiveObject
{
private readonly ObservableCollection<TimeSpanItem> _options;
private TimeSpanItem _selectedOption;
public ReadOnlyObservableCollection<TimeSpanItem> Options { get; }
public TimeSpanItem SelectedOption { get => _selectedOption; set => this.RaiseAndSetIfChanged( ref _selectedOption, value ); }
public MainViewModel()
{
_options = new ObservableCollection<TimeSpanItem>();
Options = new ReadOnlyObservableCollection<TimeSpanItem>( _options );
_options.Add( new TimeSpanItem( 1, TimeSpanKind.Week ) );
_options.Add( new TimeSpanItem( 1, TimeSpanKind.Month ) );
_options.Add( new TimeSpanItem( 3, TimeSpanKind.Month ) );
_options.Add( new TimeSpanItem( 6, TimeSpanKind.Month ) );
_options.Add( new TimeSpanItem( 1, TimeSpanKind.Year ) );
SelectedOption = _options.Last();
}
}
and some data types:
public enum TimeSpanKind
{
M = 2,
W = 1,
Y = 3,
Week = W,
Month = M,
Year = Y,
}
public class TimeSpanItem
{
public TimeSpanItem( int value, TimeSpanKind kind )
{
Value = value;
Kind = kind;
}
public int Value { get; }
public TimeSpanKind Kind { get; }
public override string ToString()
{
return $"{Value}{Kind}";
}
}
Now it is time for the presentation. The easiest way to present a selectable collection is a ListBox or ListView because everything can be wired up in XAML
<Window
x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Grid>
<ListBox
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
Margin="5"
Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock
MinWidth="40"
Margin="5"
Text="{Binding}"
TextAlignment="Center" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
and that is the result

Related

After navigating back button command is not responding to click

I am trying to learn .NET Maui by building a simple app like the android Contacts app. I have a main page that has a list of items with a floating button at the bottom to add a new item as shown in the xaml below. When the user clicks on the imagebutton I navigate to a CreatePage that allows the user to enter the values for each field in an Account object. I am using the CommunityToolkit.MVVM library to handle the MVVM stuff.
In MainPageViewModel I navigate to the CreatePage using the "Shell.Current.GoToAsync(route)" in the CreateNewAccount method shown in the MainPageViewModel:
This works fine for the first time I navigate to add a new Account. When I navigate back to the MainPage and try to click the imagebutton again to add another Account the button is non-responsive. I do not see why it is not handling the button click when I navigated back. Any thoughts?
This is part of the XAML in MainPage.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CollectionView Grid.Row="0"
Background="Transparent"
IsGrouped="False"
ItemSizingStrategy="MeasureAllItems"
ItemsLayout="VerticalList"
ItemsSource="{Binding Accounts}"
SelectedItem="{Binding SelectedAccount, Mode=TwoWay}"
SelectionMode="Single">
<CollectionView.EmptyView>
<StackLayout Padding="12">
<Label HorizontalOptions="Center" Text="No Accounts" />
</StackLayout>
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="m:Account">
<StackLayout Orientation="Horizontal" Padding="10">
<Label Text="{Binding AccountName}"
FontSize="Large"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
<ImageButton
Grid.Row="0"
Command="{Binding CreateCommand}"
Source="add_box_black_48dp.svg"
Background="Transparent"
HorizontalOptions="End"
VerticalOptions="End"/>
</Grid>
public class MainPageViewModel : ObservableObject
{
private IDataContext _context;
private bool _isBusy;
private Account _selectedAccount;
public ObservableCollection<Account> Accounts { get; private set; }
public AsyncRelayCommand RefreshCommand { get; private set; }
public AsyncRelayCommand CreateCommand { get; private set; }
public bool IsBusy { get=>_isBusy; set => SetProperty(ref _isBusy, value); }
public Account SelectedAccount { get=>_selectedAccount; set => SetProperty(ref _selectedAccount, value); }
public MainPageViewModel(IDataContext context)
{
_context = context;
Accounts = new ObservableCollection<Account>();
RefreshCommand = new AsyncRelayCommand(Refresh);
CreateCommand = new AsyncRelayCommand(CreateNewAccount);
Accounts.Add(new Account { Id = 1, AccountName = "a1", UserName = "a2", Password = "a3" });
}
async Task CreateNewAccount()
{
var route = $"{nameof(CreatePage)}";
await Shell.Current.GoToAsync(route);
}
internal async Task InitializeAsync()
{
await Refresh();
}
async Task Refresh()
{
IsBusy = true;
var accounts = await _context.GetAllAsync();
if (Accounts.Count > 0)
{
Accounts.Clear();
}
foreach (var item in accounts)
{
Accounts.Add(item);
}
IsBusy = false;
}
}
In CreatePageViewModel I create an AsyncRelayCommand as follows and navigate back to the mainpage after the Account is added using "Shell.Current.GoToAsync("..")"
public AsyncRelayCommand SaveCommand { get; private set; }
public CreatePageViewModel(IDataContext dataContext)
{
_dataContext = dataContext;
NewAccount = new Account();
SaveCommand = new AsyncRelayCommand(AddAccount);
}
private async Task AddAccount()
{
var accountFound = await _dataContext.FindByName(NewAccount.AccountName);
if (accountFound is not null)
{
await Application.Current.MainPage.DisplayAlert("Alert", "Account alreaady exists", "OK");
return;
}
await _dataContext.InsertAccountAsync(NewAccount);
await Shell.Current.GoToAsync("..");
}
why you await all events?
async Task CreateNewAccount()
{
var route = $"{nameof(CreatePage)}";
// we won't wait - await Shell.Current.GoToAsync(route);
_ = Shell.Current.GoToAsync(route);
}
and everything will work

Bind ProgressRing to mvvm

I am downloading data from an api, and displaying that data in the view. As I wait I want to display a ProgressRing, but when I bind it dosen't work
Bind the ring to the cityData property, with a two way mode and update it when the property changes
Created a new property in the VM, that is true by default and it will turn false when I get the data back
XAML
<TextBox x:Name="currentLocation"
PlaceholderText="Please wait..."
IsReadOnly="True"
Margin="20"
Width="300"
Text="{Binding cityData, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<ListView RelativePanel.Below="currentLocation"
x:Name="ForecastList"
Margin="20"
SelectedItem="{Binding currentDay, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding dailyForecasts}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="10">
<TextBlock x:Name="dateTB" Text="{Binding Date.DayOfWeek}" />
<TextBlock x:Name="highTB" Text="{Binding Temperature.Maximum.Value, Converter={StaticResource cv}}" FontSize="10" />
<TextBlock x:Name="lowTB" FontSize="10" Text="{Binding Temperature.Minimum.Value, Converter={StaticResource cv}}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ProgressRing x:Name="pRing" RelativePanel.Above="ForecastList" RelativePanel.AlignHorizontalCenterWith="currentLocation" IsActive="{Binding ring, Mode=TwoWay}" RelativePanel.Below="currentLocation" />
VM
public class WeatherVM: INotifyPropertyChanged
{
public AccuWeather accuWeather { get; set; }
private string _cityData;
public string cityData
{
get { return _cityData; }
set
{
if (value != _cityData)
{
_cityData = value;
onPropertyChanged("cityData");
GetWeatherData();
}
}
}
private DailyForecast _currentDay;
public DailyForecast currentDay
{
get { return _currentDay; }
set
{
if (value != _currentDay) \
{
_currentDay = value;
onPropertyChanged("currentDay");
}
}
}
public bool ring { get; set; } = true;
public ObservableCollection<DailyForecast> dailyForecasts { get; set; }
public WeatherVM()
{
GetCuurentLocation();
dailyForecasts = new ObservableCollection<DailyForecast>();
}
private async void GetCuurentLocation() {
cityData = await BingLocator.GetCityData();
}
public async void GetWeatherData() {
var geoposition = await LocationManager.GetGeopositionAsync();
var currentLocationKey = await WeatherAPI.GetCityDstaAsync(geoposition.Coordinate.Point.Position.Latitude, geoposition.Coordinate.Point.Position.Longitude);
var weatherData = await WeatherAPI.GetWeatherAsync(currentLocationKey.Key);
if (weatherData != null) {
foreach (var item in weatherData.DailyForecasts) {
dailyForecasts.Add(item);
}
}
currentDay = dailyForecasts[0];
ring = false;
}
public event PropertyChangedEventHandler PropertyChanged;
private void onPropertyChanged(string property) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
}
}
}
The progress ring appears when the app launch, and disappear when the data is returned
From your code, it seems to be a layout issue. First you put ListView below currentLocation, then set ProgressRing above ListView and below currentLocation, so the height of ProgressRing wil be zero. I'm not clear about your layout, you can try to only set RelativePanel.Above="ForecastList" for ProgressRing to see if it will appear.
You can use Windows Community Toolkit control for showing progress ring (Busy indicator).
<Page ...
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"/>
<controls:Loading x:Name="LoadingControl" IsLoading="{Binding IsBusy}">
<!-- Loading screen content -->
</controls:Loading>

Master/Details binding MVVM

I have some problem with correct binding my folder with images to master details and other operation with them.
So, I have model of folder and image
public class AppFolder
{
private long id;
private List<AppImage> appImages;
public AppFolder() { }
public List<AppImage> AppImages { get => appImages; set => appImages = value; }
public long Id { get => id; set => id = value; }
}
public class AppImage
{
private int id;
private string title;
private ImageSource appImageURL;
public AppImage() { }
public AppImage(string title, ImageSource imageSource)
{
Title = title;
AppImageURL = imageSource;
}
public int Id { get => id; set => id = value; }
public string Title { get => title; set => title = value; }
public ImageSource AppImageURL { get => appImageURL; set => appImageURL = value; }
}
And I bind List to Master/Details.
public class UserPhotosViewModel : ViewModelBase
{
private readonly IDataService dataService;
private readonly INavigationService navigationService;
public UserPhotosViewModel(IDataService dataService, INavigationService navigationService)
{
this.dataService = dataService;
this.navigationService = navigationService;
Initialize();
}
private async Task Initialize()
{
var item = new List<AppFolder>();
try
{
item = await dataService.GetDataList();
FolderList = item;
}
catch (Exception ex)
{
}
}
private List<AppFolder> folderList;
public List<AppFolder> FolderList
{
get { return folderList; }
set
{
folderList = value;
RaisePropertyChanged(nameof(FolderList));
}
}
}
Example xaml file
<controls:MasterDetailsView ItemsSource="{Binding FolderList}">
<controls:MasterDetailsView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}"></TextBlock>
</DataTemplate>
</controls:MasterDetailsView.ItemTemplate>
<controls:MasterDetailsView.DetailsTemplate>
<DataTemplate>
<controls:AdaptiveGridView ItemsSource="{Binding AppImages}"
OneRowModeEnabled="False"
ItemHeight="205"
DesiredWidth="205"
SelectionMode="Multiple"
Margin="0 6 0 0"
>
<controls:AdaptiveGridView.ItemTemplate>
<DataTemplate >
<Grid Background="White" Margin="10">
<Image
Source="{Binding AppImageURL}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
/>
<TextBlock Text="{Binding TextTitle}"></TextBlock>
</Grid>
</DataTemplate>
</controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>
</DataTemplate>
</controls:MasterDetailsView.DetailsTemplate>
</controls:MasterDetailsView>
So, it's work correct and I saw my folders with images on page
enter image description here
Look nice and I think it all.
But when I want to add event and SelectedItem to AdaptiveGridView from MVVM model, I saw that it doesn't see them. Visual Studio show me that I could to write them in Model "AppFolder" but it's nonsens....
So, my question: How I can add event (binding command/method) to adaptive grid from UserPhotosViewModel?
Thank you for your time.
UPDATE
enter image description here
2) User double click on image and program send folder with this image and other to page and binding them to FlipView (imitation full screen viewer)
I try to add, but that way also offers to write event and property in model. I use this way for settings in navigation panel (parent control for master/details)
You just need to add command property in your AppFolder class like the following:
public class AppFolder:ViewModelBase
{
private long id;
private List<AppImage> appImages;
public AppFolder() { }
public List<AppImage> AppImages { get => appImages; set => appImages = value; }
public long Id { get => id; set => id = value; }
public RelayCommand<object> relayCommand { get; set; }
}
Then, in your UserPhotosViewModel, you could declare a method for initializing this command.
Since I do not know what the dataService.GetDataList() is. I just change this place in your code and make a simple code sample for you.
private void Initialize()
{
var item = new List<AppFolder>();
try
{
List<AppImage> ls = new List<AppImage>();
ls.Add(new AppImage() { Id = 1, Title = "aaa", AppImageURL = new BitmapImage(new Uri("ms-appx:///Assets/1.jpg")) });
ls.Add(new AppImage() { Id = 2, Title = "bbb", AppImageURL = new BitmapImage(new Uri("ms-appx:///Assets/2.jpg")) });
item.Add(new AppFolder() { Id = 1, AppImages = ls,relayCommand=new RelayCommand<object>(DoubleTapCommand) });
FolderList = item;
}
catch (Exception ex)
{
}
}
private void DoubleTapCommand(object obj)
{
//the obj will be an AppFolder object
}
<controls:MasterDetailsView.DetailsTemplate>
<DataTemplate>
<controls:AdaptiveGridView x:Name="grid" ItemsSource="{Binding AppImages}"
OneRowModeEnabled="False"
ItemHeight="205"
DesiredWidth="205"
SelectionMode="Multiple"
Margin="0 6 0 0">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="DoubleTapped">
<Interactions:InvokeCommandAction Command="{Binding relayCommand}" CommandParameter="{Binding}"></Interactions:InvokeCommandAction>
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
<controls:AdaptiveGridView.ItemTemplate>
<DataTemplate >
<Grid Background="White" Margin="10">
<Image
Source="{Binding AppImageURL}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Stretch="Uniform"
/>
<TextBlock Text="{Binding TextTitle}"></TextBlock>
</Grid>
</DataTemplate>
</controls:AdaptiveGridView.ItemTemplate>
</controls:AdaptiveGridView>
</DataTemplate>
</controls:MasterDetailsView.DetailsTemplate>
1) User select N images and delete them (example)
About this requirement, I suggested that you'd better add a button to bind command for deleting selected items.

Binding content inside usercontrol in WPF MVVM

This is what I have. A mainwindow with a combobox and a tabcontrol in it, having a viewmodel attached to its datacontext.
I have a usercontrol with another viewmodel , this usercontrol contains a combobox and a datagrid.Now when I select an item from the main combobox , the viewmodel will calculate how many tabs need to be generated at runtime, and it assigns the usercontrol to each tabitem. The problem I am having is , I am unable to bind the items to be populated in the combobox of each usercontrol tab item. Below is my code
MainWindow.xaml
<Window x:Class="TsstApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:TsstApp"
WindowState="Maximized"
Title="MainWindow" Height="1333" Width="1024">
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="21,22,0,0" VerticalAlignment="Top"
Width="120" ItemsSource="{Binding Items}" DisplayMemberPath="ItemName" SelectedItem="
{Binding SelectedItem}"/>
<TabControl HorizontalAlignment="Left" Height="928" Margin="10,69,0,0"
VerticalAlignment="Top" Width="996" ItemsSource="{Binding TabData}">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Tech}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<vm:TabItemControl/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
Below is the mainviewmodel
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
private ItemCollection selectedItem;
public MainViewModel()
{
List<ItemCollection> ax = new List<ItemCollection>();
ax.Add(new ItemCollection() { ItemId = 0, ItemName = "Hair" });
ax.Add(new ItemCollection() { ItemId = 1, ItemName = "Fur" });
ax.Add(new ItemCollection() { ItemId = 2, ItemName = "Tail" });
this.Items = ax;
RaisePropertyChanged("Items");
this.SelectedItem = this.Items[0];
RaisePropertyChanged("SelectedItem");
}
public IList<ItemCollection> Items { get; set; }
public ItemCollection SelectedItem
{
get { return selectedItem ;}
set {
selectedItem = value;
RaisePropertyChanged("SelectedItem");
List<TabItemData> tabs = new List<TabItemData>();
switch(selectedItem.ItemName)
{
case "Hair":
for (int i = 0; i < 5;i++)
{
tabs.Add(new TabItemData() { TabId = i, TabName = "Hair"+i.ToString() });
}
break;
case "Fur":
for (int i = 0; i < 3; i++)
{
tabs.Add(new TabItemData() { TabId = i, TabName = "Fur" + i.ToString() });
}
break;
case "Tail":
for (int i = 0; i < 7; i++)
{
tabs.Add(new TabItemData() { TabId = i, TabName = "Tail" + i.ToString() });
}
break;
}
SelectedItem.TabData = tabs;
this.TabData = tabs.Select(t => new TabItemViewModel(t)).ToList();
RaisePropertyChanged("TabData");
}
}
public IList<TabItemViewModel> TabData { get; private set; }
}
Below is my usercontrol
UserControl.xaml
<UserControl x:Class="TsstApp.TabItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:vm="clr-namespace:TsstApp"
mc:Ignorable="d"
d:DesignHeight="1333" d:DesignWidth="1024">
<UserControl.DataContext>
<vm:TabItemViewModel/>
</UserControl.DataContext>
<Grid>
<ComboBox HorizontalAlignment="Left" Margin="75,91,0,0" VerticalAlignment="Top"
Width="148" Height="27" ItemsSource="{Binding ReleaseItems}"
SelectedValuePath="ItemId" DisplayMemberPath="ItemName"/>
<TextBox HorizontalAlignment="Left" Height="31" Margin="75,183,0,0"
TextWrapping="Wrap" Text="{Binding TextContent}" VerticalAlignment="Top" Width="148"/>
</Grid>
</UserControl>
And this is the viewmodel
TabItemViewModel.cs
public class TabItemViewModel : ViewModelBase
{
public TabItemViewModel()
{
}
public TabItemViewModel(TabItemData t)
{
this.Tech = t.TabName;
List<TabReleases> az = new List<TabReleases>();
for(int i=0;i<10;i++)
{
az.Add(new TabReleases(){ReleaseId=i , ReleaseName=t.TabName + "-" + i.ToString()});
}
this.ReleaseItems = az;
}
public string Tech { get; set; }
public IList<TabReleases> ReleaseItems { get; set; }
}
Now , the tabitem header , is working fine , as you can see , I am binding the header in the mainwindows iteself, but the combobox of the usercontrol is not getting popualated.
Kindlyhelp.
I solved it finally. I was just doing one thing wrong. I was adding datacontect in the tabitemcontrol , but it is not required , as tabcontrol in mainwindows already has itemsource , which creates instances to tabitemview model

RaisePropertyChanged doesn't work for ObservableCollection

I have a really weird problem with update UI using MVVM Light Toolkit. The RaisePropertyChanged doesn't work at all for my ObservableCollection.
Here is the XAML code:
<ListBox x:Name="list" ItemsSource="{Binding ModelList}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<CheckBox IsChecked="{Binding IsChecked}"></CheckBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<interaction:Interaction.Triggers>
<interaction:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding TempCommand}" CommandParameter="{Binding ElementName=list, Path=SelectedItem}"
PassEventArgsToCommand="True"/>
</interaction:EventTrigger>
</interaction:Interaction.Triggers>
</ListBox>
And there is ViewModel code part:
private Model _selectedItem;
public Model SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
private ObservableCollection<Model> _modelList;
public ObservableCollection<Model> ModelList
{
get { return _modelList; }
set
{
_modelList = value;
RaisePropertyChanged("ModelList");
}
}
public RelayCommand<Model> TempCommand { get; private set; }
/// <summary>
/// Initializes a new instance of the MainViewModel class.
/// </summary>
public MainViewModel()
{
modelList = new ObservableCollection<Model>()
{
new Model()
{
IsChecked = true,
Name = "Temp1"
},
new Model()
{
IsChecked = false,
Name = "Temp2"
},
new Model()
{
IsChecked = false,
Name = "Temp3"
}
};
ModelList = modelList;
TempCommand = new RelayCommand<Model>(Model_SelectedItem);
}
private void Model_SelectedItem(Model item)
{
// What should I do here?
}
When I change the ModelList - there is no reaction from ListBox UI.
Anyone can help me ?
Problem solved.
When you have custom class in ObservableCollection or List it has to derived from ObservableObject and all the Properties have to fire RaisePropertyChanged event.