Header element within a ListView in UWP - c#

I'd like to have a header element in my ListView, but I need the possibility to decide which item is simple and which one is header when I bind data to the ListView. This header should not be clickable and have a different color at least. In Android we do it in a custom adapter.
At the moment I get this logic of data binding to the ListView:
<ListView
x:Name="drawerListOptions"
SelectionChanged="onSelectDrawerItem"
SelectionMode="Single">
<ListView.ItemTemplate>
<DataTemplate>
<!--for simplicity I put only one view in as a list item -->
<TextBlock
Text="{Binding titleItemMenu}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and C# code:
drawerListOptions.ItemsSource = myListOfData;
So I need to check in my myListOfData if item is simple or header. Is there a way to do it?

by using CollectionViewSource
although i have the same problem, i searched over web but couldn't find solution so i create this one to load data from server and show in list as group separated as StickyHeaderListView in android.
in XAML
<Page
....
>
<RelativePanel ... >
<Page.Resources>
<CollectionViewSource x:Key="cvs" x:Name="cvs" SourceGrouped="True"/>
</Page.Resources>
<ListView x:Name="listView" IsItemClickEnabled="True" ItemsSource="{Binding Source={StaticResource `cvs` }}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate >
<RelativePanel HorizontalAlignment="Stretch" VerticalAlignment="Center" BorderBrush="DarkGray" BorderThickness="0,0,0,1" Background="White" Padding="10">
<TextBlock Text="{Binding Description}" RelativePanel.AlignVerticalCenterWithPanel="True" VerticalAlignment="Center" Foreground="Gray" FontSize="20"></TextBlock>
<StackPanel Orientation="Horizontal" RelativePanel.AlignRightWithPanel="True" RelativePanel.AlignVerticalCenterWithPanel="True" Margin="0,0,8,0" >
<TextBlock Text="{Binding Amount}" HorizontalAlignment="Right" VerticalAlignment="Center" Foreground="{StaticResource primary}" FontSize="16"/>
</StackPanel>
</RelativePanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate >
<DataTemplate>
<TextBlock Text="{Binding Key}" FontSize="14" Foreground="#FF222222" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="ListViewHeaderItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</RelativePanel> </Page>
and in source file
bind source
var obj = JsonConvert.DeserializeObject<List<Model.YourModelHere>>(ApiResponseHere);
var groups = from Data in obj group Data by Data.Date;
this.cvs.Source = groups;

Have an property in you collection item called IsSimple. In your xaml bind that variable to Header property of list view with converter. That Converter converts bool to Visibility. If value us true converter should return Visibility.Collapsed.

In UWP, we can use CollectionViewSource to provides a data source that adds grouping and current-item support to collection classes.
Use CollectionViewSource when you want to bind list controls to collections, but you want to display those collections in groups and maintain a current item independent from the list control.
For more info, see CollectionViewSource.
In my words, when you want bind to the collections and display those collections in groups without manipulating, we can use CollectionViewSource in this scenario.
You can use LINQ query to get results from the ObservableCollection. And you can set the results to the CollectionViewSource.Source.
In ListView, we can set the ListView.ItemSource bind to CollectionViewSource.View. It can get the view object that is currently associated with this instance of CollectionViewSource.
For example:
Create GroupInfoList class:
public class GroupInfoList : List<object>
{
public object Key { get; set; }
}
Create Text class:
public class Text : INotifyPropertyChanged
{
private string _title;
public string Title
{
get { return _title; }
set
{
_title = value;
RaisePropertyChanged("Title");
}
}
public Text(string name)
{
this.Title = name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Add Header class:
public class Header
{
public string HeaderTitle { get; set; }
public Header()
{
HeaderTitle = string.Empty;
}
public static ObservableCollection<Text> GetTexts()
{
ObservableCollection<Text> myListOfData = new ObservableCollection<Text>();
myListOfData.Add(new Text("Product1"));
myListOfData.Add(new Text("Product2"));
myListOfData.Add(new Text("Product3"));
myListOfData.Add(new Text("Setting1"));
myListOfData.Add(new Text("Setting2"));
myListOfData.Add(new Text("Setting3"));
myListOfData.Add(new Text("Setting4"));
return myListOfData;
}
public static ObservableCollection<GroupInfoList> GetItemsGrouped()
{
ObservableCollection<GroupInfoList> groups = new ObservableCollection<GroupInfoList>();
var query = from item in GetTexts()
group item by item.Title[0] into g
orderby g.Key
select new { GroupName = g.Key, Items = g };
foreach (var g in query)
{
GroupInfoList info = new GroupInfoList();
if (g.GroupName.ToString() == "P")
{
info.Key = "Products";
}
else if (g.GroupName.ToString() == "S")
{
info.Key = "Settings";
}
else
{
info.Key = g.GroupName;
}
foreach (var item in g.Items)
{
info.Add(item);
}
groups.Add(info);
}
return groups;
}
}
In XAML:
<Page.Resources>
<CollectionViewSource x:Name="MyItems" IsSourceGrouped="True" />
<DataTemplate x:Name="ItemListViewTemplate">
<TextBlock Text="{Binding Title}"></TextBlock>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{x:Bind MyItems.View}"
SelectionMode="Single"
ShowsScrollingPlaceholders="True"
Grid.Row="1"
ItemTemplate="{StaticResource ItemListViewTemplate}"
Grid.ColumnSpan="2">
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Foreground="Red" Text="{Binding Key}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
Set the CollectionViewSource source in code behind:
public MainPage()
{
this.InitializeComponent();
MyItems.Source = Header.GetItemsGrouped();
}

Related

How to display a checked check box on the selected item of a ListView in uwp

I have a listview in uwp where i have to highlight the selected item by displaying the checked checkbox on the selected item. So please tell me how i achieved it.
My XAML code
<ListView x:Name="gvProcesses" SelectionChanged="GvProcesses_SelectionChanged" Grid.Row="1" Grid.ColumnSpan="2" Height="100" ItemsSource="{Binding ScanProcessNameCollection,Mode=OneWay}" SelectedItem="{Binding SelectedScanProcessName,Mode=TwoWay}" IsItemClickEnabled="True" SelectionMode="Single" ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.IsHorizontalRailEnabled="True" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<!--<StackPanel Orientation="Horizontal" />-->
<ItemsStackPanel Orientation="Horizontal" Margin="0"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate >
<StackPanel Background="{ThemeResource SystemControlBackgroundAccentBrush}" >
<TextBlock Visibility="{Binding IsSelected,Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}, Converter={StaticResource BooleanToVisibilityConverter}}"
x:Name="txtcheckbox" FontFamily="Segoe MDL2 Assets" Text="" FontSize="{ StaticResource SmallFontSize}" VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
<TextBlock Text="{Binding}" FontSize="{ StaticResource SmallFontSize}" VerticalAlignment="Center" TextWrapping="WrapWholeWords" Margin="0 40" HorizontalAlignment="Center"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="2,0,2,0" />
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="MinHeight" Value="50" />
<Setter Property="MaxHeight" Value="100" />
<Setter Property="MaxWidth" Value="80" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
checkboxes display on all items binding not work properly and It also not goes on converter when i debug it.
Selection Mode Multiple
If you need multiple selection with checkbox then you can change the property SelectionMode to Multiple and then set IsMultiSelectCheckBoxEnabled to True
Selection Mode Single
If you need single selection with checkbox you need to add checkbox to your grid and then bind it to a veriable. I have added a small example below
//Xaml Code
<ListView ItemsSource="{x:Bind line_items,Mode=OneWay}" SelectionChanged="ListView_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding is_checked,Mode=OneWay}"></CheckBox>
<TextBlock Text="{Binding value,Mode=OneWay}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
//C# Code
public sealed partial class MainPage : Page
{
public List<item> line_items = new List<item>();
public MainPage()
{
for (var i = 0; i < 10; i++)
line_items.Add(new item() { is_checked = false, value = "item" + i });
this.InitializeComponent();
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach(var item in line_items)
item.is_checked = false;
line_items[(sender as ListView).SelectedIndex].is_checked = true;
}
}
public class item : INotifyPropertyChanged
{
private bool? _is_checked;
private string _value;
public bool? is_checked
{
get { return _is_checked; }
set
{
_is_checked = value;
RaisePropertyChanged(nameof(is_checked));
}
}
public string value
{
get { return _value; }
set
{
_value = value;
RaisePropertyChanged(nameof(value));
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
}

Select text from a list view when that is cliked C# Metro App

I have a list view which I populate it from an API.. I want it fill a text box with the value which is found in the text block when I click..
My Listview...
<ListView Width="300" Height="134" x:Name="lsvObjectives" IsItemClickEnabled="True" SelectionMode="Multiple" ItemsSource="{Binding Source={StaticResource cvsObjectives}}" ItemClick="lsvObjectives_ItemClick">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Orientation="Horizontal" HorizontalChildrenAlignment="left"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="-7"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="0,0,0,0" HorizontalAlignment="Center" >
<StackPanel Orientation="Horizontal" Width="310" Height="33" Background="#FFE9D5F0" HorizontalAlignment="Left">
<StackPanel Width="270" VerticalAlignment="Center" Margin="10,5,0,0">
<TextBlock Text="{Binding objective}" Style="{StaticResource ContentTextBlockStyle}" Foreground="Black" VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="13"/>
</StackPanel>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how I populate the list:
private async void getObjectives()
{
string getObjectives = baseAddress + "unitPlansDetailsByUnit/1";
var content = await httpClient.GetStringAsync(new Uri(getObjectives));
objectivesHelper data = JsonConvert.DeserializeObject<objectivesHelper>(content);
foreach (var item in data.result)
{
cvsObjectives.Source = data.result;
}
}
My Classes:
public class objectives
{
public int id { get; set; }
public string objective { get; set; }
}
class objectivesHelper
{
public List<objectives> result { get; set; }
}
I am unable to read the value from the text block which is found in my list view..
Someone kindly help me do this..
Any kind of help is appreciated....
You can read the value in your lsvObjectives_ItemClick method by casting the ItemClickEventArgs.ClickedItem to your type objectives.
For example:
private void lsvObjectives_ItemClick(object sender, ItemClickEventArgs e)
{
objectives item = e.ClickedItem as objectives;
var itemText = item.objective;
youtTextBox.Text = item.Description.ToString();
}

In PivotItem, ListBox Binding dont show value

Im create collection for show in ListBoxTransactions and binding as Description. But in result i have only name collection in ListBoxTransactions.ItemsSource, but not value. adn a cant use ListBox.ItemTemplate
XAML
<phone:PivotItem Header="Journal">
<Grid>
<ListBox Name="ListBoxTransactions">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}" FontSize="35"/>
</StackPanel>
</ListBox>
</Grid>
</phone:PivotItem>
C#
public class TransactHelper
{
public string Description { get; set; }
}
public void ShowTransactions()
{
ListBoxTransactions.Items.Clear();
var transactFulls = _workerDb.GeTransactFull();
var list = new List<TransactHelper>();
foreach (var t in transactFulls)
{
list.Add(new TransactHelper { Description = t.Description });
}
this.ListBoxTransactions.ItemsSource = list; // dont view collection. only name collection
You should implement ItemContainerStyle for your items.
<ListBox Name="ListBoxTransactions" ItemContainerStyle="{DynamicResource MyItemStyle}">
<ListBox.Resources>
<Style x:Key="MyItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Description}" FontSize="35"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.Resources>
</ListBox>
And once note:
Don't use this pair
ListBoxTransactions.Items.Clear();
this.ListBoxTransactions.ItemsSource = list;
You need
ListBoxTransactions.ItemsSource = null;
this.ListBoxTransactions.ItemsSource = list;
Or Implement your collection as ObservableCollection

WPF ComboBox selection change after switching tabs

I made a project based on nested tabs.
the nested tabs are different instance of the same viemModel and the same UI.
when I switch between the tabs he comboboxes present in the tabs chenge thei selection depending on the tab that is loosing focus.
I add both the viewmodels and the view of my test project.
thank you in advance for your help
main window
<Window.Resources>
<DataTemplate DataType="{x:Type local:IntermediateViewModel}">
<local:IntermediateView />
</DataTemplate>
<DataTemplate x:Key="HeaderedTabItemTemplate">
<Grid>
<ContentPresenter
Content="{Binding Path=Header, UpdateSourceTrigger=PropertyChanged}"
VerticalAlignment="Center" >
</ContentPresenter>
</Grid>
</DataTemplate>
<Style x:Key="SimpleTabItemStyle" TargetType="TabItem">
<Setter Property="Foreground" Value="White"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border" BorderThickness="1" BorderBrush="#555959">
<ContentPresenter x:Name="ContentSite" VerticalAlignment="Center" HorizontalAlignment="Center"
ContentSource="Header" Margin="12,2,12,2" RecognizesAccessKey="True" Height ="40" MinWidth ="90"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Border" Property="Background" Value="#555959" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="DefaultTabControlTemplate">
<TabControl IsSynchronizedWithCurrentItem="True"
BorderThickness="0"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource HeaderedTabItemTemplate}"
ItemContainerStyle="{StaticResource SimpleTabItemStyle}"
SelectionChanged="TabControl_SelectionChanged"
/>
</DataTemplate>
<!---->
</Window.Resources>
<Grid MinHeight="200" MinWidth="300">
<Grid.RowDefinitions>
<RowDefinition Height="260*" />
<RowDefinition Height="51*" />
</Grid.RowDefinitions>
<Border >
<ContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{DynamicResource DefaultTabControlTemplate}"
/>
</Border>
<Button Grid.Row="1" Content="Add" Command="{Binding AddCommand}"/>
</Grid>
view model (create a different istance each time)
class MainWindowViewModel : WorkspacesViewModel<IntermediateViewModel>
{
public MainWindowViewModel()
{
this.WorkspacesView.CurrentChanged += new EventHandler(WorkspacesView_CurrentChanged);
}
void WorkspacesView_CurrentChanged(object sender, EventArgs e)
{
}
RelayCommand myVar = null;
public ICommand AddCommand
{
get
{
return myVar ?? (myVar = new RelayCommand(param =>
{
SetWindow(new IntermediateViewModel("AA" + this.Workspaces.Count) );
}));
}
}
first level tab
<UserControl.Resources>
<DataTemplate DataType="{x:Type local:ClassViewModel}">
<local:ClassView />
</DataTemplate>
</UserControl.Resources>
<Border>
<ContentControl Content="{Binding Path=CurrentWorkspace, Mode=OneWay}" Loaded="ContentControl_Loaded" DataContextChanged="ContentControl_DataContextChanged" IsVisibleChanged="ContentControl_IsVisibleChanged" LayoutUpdated="ContentControl_LayoutUpdated" TargetUpdated="ContentControl_TargetUpdated" Unloaded="ContentControl_Unloaded" />
</Border>
first level viewmodel
class IntermediateViewModel : WorkspacesViewModel
{
public string Header { get; set; }
public IntermediateViewModel(string header)
{
Header = header;
SetWindow(new ClassViewModel(header));
}
}
nested tab
<UserControl.Resources>
<CollectionViewSource x:Key="StatusView" Source="{Binding Path=StatusList}"/>
</UserControl.Resources>
<Grid>
<ComboBox Name="_spl2Status" ItemsSource="{Binding Source={StaticResource StatusView}}"
SelectedValue="{Binding Path=MyProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="FL_TYPE"
DisplayMemberPath="ID_TYPE" Margin="76,12,0,0" Height="40" VerticalAlignment="Top" HorizontalAlignment="Left" Width="146"
DataContextChanged="_spl2Status_DataContextChanged"
IsVisibleChanged="_spl2Status_IsVisibleChanged"
Loaded="_spl2Status_Loaded"
SelectionChanged="_spl2Status_SelectionChanged"
>
</ComboBox>
</Grid>
nested tab view model
public enum myTypes
{
tipo0 = 0,
tipo1 = 1,
tipo2 = 2,
}
class ClassViewModel : WorkspaceViewModel
{
public ClassViewModel(string name)
{
Name = name;
}
public string Name { get; set; }
private List<IntEnumType> _statusList = null;
public List<IntEnumType> StatusList
{
get
{
if (_statusList == null)
_statusList = new List<IntEnumType>()
{
new IntEnumType((int)myTypes.tipo0, myTypes.tipo0.ToString()),
new IntEnumType((int)myTypes.tipo1, myTypes.tipo1.ToString()),
new IntEnumType((int)myTypes.tipo2, myTypes.tipo2.ToString()),
};
return _statusList;
}
}
private int myVar = 1;
public int MyProperty
{
get
{
return myVar;
}
set
{
if (myVar != value)
{
myVar = value;
OnPropertyChanged(() => MyProperty);
}
}
}
}
public class TabItemStyleSelector : StyleSelector
{
public Style MainTabItem { get; set; }
public Style ChildrenTabItem { get; set; }
public Style SpecificationTabItem { get; set; }
public override Style SelectStyle(object item, DependencyObject container)
{
//if (item is IHome)
// return MainTabItem;
//else if (item is SpecificationItemViewModel)
// return SpecificationTabItem;
//else
return ChildrenTabItem;
}
}
The code is a little hard to completely follow, but I'm guessing that the issue is that there is only one instance of your ClassViewModel and it is where the selection for the combo box is stored {Binding Path=MyProperty, so whatever is stored in MyProperty will be reflected in all instances of the combo box regardless of where they live.
Well this is a bit late, but as I'm facing the same issue, I want to share my analysis.
When you change your tabs, you change the DataContext of the current Tab to your other ViewModel and hence also the ItemsSource of your ComboBox.
In case your previously selected Item (SelectedItem) is not contained within the new ItemsSource, the ComboBox fires a SelectionChanged-Event and therefore sets the SelectedIndex to -1.
Altough this default behaviour of the ComboBox might make sense, it's very annoying in many cases.
We've derived an own class from ComboBox, handling that. But it's not very satisfying as you loose some default behaviour you most probably need.
The problem is in your loaded event handlers.
When you switch tabs your unloading one tab and loading a new one.
I suspect your changing MyComboBox.SelectedIndex in _spl2Status_Loaded.

unable to get, set selectedItem from the listbox containing radiobuttons being generated dynamically in wpf MVVM

Am trying to populate listbox with dynamic radiobuttons which are being customized to togglebuttons. I could populate listbox items with radiobuttons as said above. However, once we select any of the radiobuttons am unable to set the selected item from list of radiobuttons in my viewmodel object while debugging.
The following is the xaml code in my resource directory
<Style x:Key="ScreensList" TargetType="{x:Type ListBox}">
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="2, 2, 2, 0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Background="Transparent">
<RadioButton
VerticalAlignment="Center" GroupName="{Binding RelativeSource={RelativeSource TemplatedParent}}"
IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}">
<RadioButton.Template>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
<StackPanel Width="80" Height="60" Orientation="Vertical" HorizontalAlignment="Left" Margin="10,10,20,10">
<Image Source="Default.png" Height="40"></Image>
<TextBlock Text="{Binding Path=ScreenNumber}" FontSize="11"></TextBlock>
</StackPanel>
</ToggleButton>
</StackPanel>
</ControlTemplate>
</RadioButton.Template>
</RadioButton>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
the below is my xaml code in xaml page
<ListBox x:Name="ScreensList" ItemsSource="{Binding ScreenCollection}"
SelectedItem="{Binding Path=ScreenManager}"
Style="{StaticResource ScreensList}" Width="365">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel FlowDirection="LeftToRight" Orientation="Horizontal" >
</WrapPanel>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
the following is the viewmodel.cs
public ObservableCollection<ScreensManager> ScreenCollection { get; set; }
private ScreensManager _screenManager;
public ScreensManager ScreenManager
{
get { return _screenManager; }
set
{
if (_screenManager != value)
{
if (_screenManager != null)
{
_screenManager = value;
}
}
}
}
private void AddScreens()
{
int screenCount = Screen.AllScreens.Length;
if (ScreenCollection == null)
ScreenCollection = new ObservableCollection<ScreensManager>();
for (int screenCounter = 1; screenCounter <= screenCount; screenCounter++)
{
if (screenCounter == 1)
{
_screenManager = new ScreensManager();
_screenManager.ScreenNumber = screenCounter;
ScreenCollection.Add(_screenManager);
}
}
}
the following is the code in my ScreenManager.cs model class file
public ScreensManager()
{
}
private int _screenNumber;
public int ScreenNumber
{
get { return _screenNumber; }
set
{
_screenNumber = value;
OnPropertyChanged("ScreenNumber");
}
}
private bool _selectedScreen;
public bool SelectedScreen
{
get { return _selectedScreen; }
set
{
if (_selectedScreen = value)
{
_selectedScreen = value;
if (_selectedScreen != value)
{
OnPropertyChanged("SelectedScreen");
}
}
}
}
private void OnPropertyChanged(string propName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
Am unable to find where I am actually going wrong as completely new to mvvm, someone please help me resolve my issue..Thanks in advance.
Your SelectedScreen is of type bool, and should be of type ScreensManager
Your ListBox.ItemsSource is bound to an ObservableCollection<ScreensManager>, meaning your ListBox contains a collection of ScreensManager objects, however your SelectedItem is of type bool. A bool object is never equal to a ScreensManager object, so WPF doesn't select anything since the SelectedItem is not found in the ItemsSource.
Change the SelectedScreen type to be ScreensManager instead of bool, and be sure it is equal to an item that exists in the ScreenCollection. WPF compares objects by reference, not value, so
ScreenManager.SelectedScreen = ScreenCollection.FirstOrDefault(); // Works
ScreenManager.SelectedScreen = new ScreensManager() { ... }; // Won't work
Make sure the binding is in two-way mode:
SelectedItem="{Binding Path=ScreenManager.SelectedScreen, Mode=TwoWay}"

Categories