Can't change gridview itemssource - c#

I'm trying to change a box's color in a gridview(that has ItemTemplates which has 100 green boxes).
First, I created a list(which typed as my class) and I added all items to list and I added list to my gridview source :
grid1.ItemsSource = boxlist;
After, I added a click event for item click on gridview. I want that when I clicked to an item, this item's color will be changed. So I edited list as it :
int id = ((Boxes)e.ClickedItem).id;
boxlist[id].color = "DarkRed";
grid1.ItemsSource = boxlist;
I tried it to change color of clicked item but it doesn't work. Color of list item is changing succesfully but gridview is not taking it. But I want that gridview takes this new source. How can I solve this problem?
My class :
class Boxes
{
public int id { get; set; }
public string color { get; set; }
}
XAML of GridView
<GridView x:Name="grid1" HorizontalAlignment="Left" Margin="354,41,0,0" VerticalAlignment="Top" Width="800" Height="650" SelectionMode="None" IsItemClickEnabled="True" ItemClick="grid1_ItemClick">
<GridView.Resources>
<DataTemplate x:Key="DataTemplate1">
<Grid Height="50" Width="50">
<Rectangle x:Name="rect1" Width="50" Height="50" Fill="{Binding color}" Tag="{Binding id}"/>
</Grid>
</DataTemplate>
</GridView.Resources>
<GridView.ItemTemplate>
<StaticResource ResourceKey="DataTemplate1"/>
</GridView.ItemTemplate>
</GridView>

You have to null the ItemSource just before you set the new value:
ctlList.ItemsSource = null;
ctlList.ItemsSource = YourObjects;
I recommand to use DataContext and Binding instead of your solution:
http://www.codeproject.com/Articles/30905/WPF-DataGrid-Practical-Examples

You need to use DataContext instead like this:
grid1.DataContext = boxlist;

Related

In wpf Clear ListBox items at Runtime

I am using wpf listbox, i cannot able to clear the list when am calling the reload data function, i just want to reload new data at runtime,while page loading it loads the data correctly, when i refresh the new data is fetched in itemsource i can see that in debug mode, but no new data in listbox, old data remains in the list, i cant even clear, when i call list.items.clear(), i tried lot ways, is there any problem in my XAML binding, the following is my code.
XAML:
<ListBox ItemsSource="{Binding}" HorizontalContentAlignment="Left" x:Name="lstbxindex" Foreground="White" FontSize="20px" Height="400" BorderBrush="#555555" Margin="10,34,16,0" VerticalAlignment="Top" Width="322" Background="#555555" >
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel Orientation="Horizontal" Margin="5" >
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtblckroundhour" Height="40px" Width="55px" Text="{Binding RoundedHours}" FontSize="14" Background="#555555" Loaded="txtblckroundhour_Loaded" Foreground="White"></TextBlock>
<Label x:Name="items" MouseDoubleClick="items_MouseDoubleClick" Content="{Binding ProjectRow.Name}" Background="#555555" FontSize="20" Loaded="items_Loaded" Visibility="Visible" Margin="35,0,0,0" Width="230" Foreground="White"></Label>
</StackPanel>
<StackPanel Orientation="Vertical">
<ComboBox Height="40px" Width="290" Margin="-230,0,0,0" Loaded="ComboBox_Loaded" Visibility="Hidden" IsEditable="True" FontSize="20" Background="White" Foreground="Black"></ComboBox>
</StackPanel>
<!--<ComboBox x:Name="ComboBox_AddItem" Height="40px" Width="290" Margin="-35,35,0,0" Loaded="ComboBox_AddItem_Loaded" IsEditable="True" FontSize="20" Background="White" Visibility="Hidden" Foreground="Black"></ComboBox>-->
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Get the list of values
private List<ProjectInformation> projectInformationList1 = new List<ProjectInformation>();
// Here define the actual binding of the userinterface listbox to the in-memory list of objects.
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataContext = projectInformationList1;
In SO I tried some solution but unfortunately it is not work for me. Last I tried,
XAML.cs page
public static readonly DependencyProperty MyListProperty = DependencyProperty.Register("MyList", typeof(ObservableCollection<String>), typeof(Window));
public ObservableCollection<String> MyList
{
get
{
return (ObservableCollection<String>)GetValue(MyListProperty);
}
set
{
SetValue(MyListProperty, value);
}
}
XAML:
<ListBox ItemsSource="{Binding **ElementName=Window**}" HorizontalContentAlignment="Left" x:Name="lstbxindex" Foreground="White" FontSize="20px" Height="400" BorderBrush="#555555" Margin="10,34,16,0" VerticalAlignment="Top" Width="322" Background="#555555" >
Using this above solution listitems are clear but when pageloading the listboxitems are clear but I don't want to clear the iistboxitems, after updating the values from user it will reload the updated value in listbox.
lstbxindex.ItemsSource = null;
But its not work.For pageload listbox loaded all items,every 15 min interval it will call the load function for firsttime it will reload the updatedvalues but second time it will reload the updated values and previous values remains in listbox again.
I misunderstood initially thinking you were using MVVM, instead you're populating the ListView datasource from code behind.
Your line lstbxindex.DataContext = projectInformationList1; does not set the Data as you'd think. Instead try lstbxindex.DataContext = this; which means you're telling your view to look for the data source in code behind.
As such, I suggest adding using System.ComponentModel; and using BindingList, a comparison is here.
private BindingList<ProjectInformation> projectInformationList1 = new BindingList<ProjectInformation>();
And you just need this once:
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataSource = projectInformationList1;
As mentioned in the comments, if you did not use ItemsSource="{Binding projectInformationList1}" as I suggested in a comment to your question, this is the alternative:
private ObservableCollection<ProjectInformation> projectInformationList1 = new ObservableCollection<ProjectInformation>();
foreach (DtoProjectsRow row in projectsTable.Rows)
{
projectInformationList1.Add(new ProjectInformation(row));
}
lstbxindex.DataContext = projectInformationList1;
You should have a view model class with a collection property, e.g. like this:
public class ViewModel
{
public ObservableCollection<ProjectInformation> Projects { get; }
= new ObservableCollection<ProjectInformation>();
}
Set the DataContext of your Window or Page in XAML like this:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
and bind the ListBox like this:
<ListBox ItemsSource="{Binding Projects}">
...
</ListBox>
To clear all items in the source collection, access the DataContext in code behind:
var vm = (ViewModel)DataContext;
vm.Projects.Clear();
Edit: Instead of assigning the DataContext in XAML, you may as well do it in code behind, even before the Page or Window is initialized:
public MainWindow()
{
DataContext = new ViewModel();
InitializeComponent();
}
Added the line in loadfunction, Initially set null for ItemSource and then set null to the list object
lstbx.ItemsSource=null;
lstbx.Items.Clear();
ProjectInfoList1=null;
it will clear the listboxitems and reload with updated values only.
private BindingList<ProjectInfo> projectInfoList1 = new BindingList<ProjectInfo>();
Public void loadfunction()
{
lstbx.ItemsSource=null;
lstbx.Items.Clear();
ProjectInformationList1=null;
foreach (DtoProRow row in table.Rows)
{
projectInfoList1.Add(new ProjectInfo(row));
}
lstbx.DataContext = projectInfoList1;
}

ListView Keep ListViewHeaderItem On Top

I start by explaining what I want to achieve:
The Letter "A" is one ListViewHeaderItem in my Listview. Without Scrolling the top of the List is looking like this.
After I am Scrolling the ListViewHeaderItem "A" is moving downwards with the rest of the items -
but how can I achieve that the Header is staying on top as Kind of the first item until the Letter "B" with ist subitems is coming? An example of the behaviour I want to achieve is the official "Mail" app for Windows 10 by Microsoft. It is keeping the datetime at the top until emails are coming which have been written one day earlier.
I don't know if this question is already existing but I don't know how it is called and I don't know what to Google for.
According to your description, I think what you want is a grouped ListView. The key points here is using CollectionViewSource as ItemsSource and setting GroupStyle to specify how groups are displayed. Following is a simple sample:
In XAML
<Page.Resources>
<CollectionViewSource x:Name="groupInfoCVS" IsSourceGrouped="True" />
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{Binding Source={StaticResource groupInfoCVS}}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Margin="15" Text="{Binding Path=Text}" />
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid Background="LightGray">
<TextBlock Margin="10" Foreground="Black" Text="{Binding Key}" />
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
</Grid>
And in code-behind
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
List<TestDemo> list = new List<TestDemo>();
for (int i = 0; i < 6; i++)
{
list.Add(new TestDemo { Key = "A", Text = $"Test A {i}" });
list.Add(new TestDemo { Key = "B", Text = $"Test B {i}" });
}
var result = from t in list group t by t.Key;
groupInfoCVS.Source = result;
}
}
public class TestDemo
{
public string Key { get; set; }
public string Text { get; set; }
}
And it looks like:
For more info, please see How to group items in a list or grid (XAML) and Simple ListView Sample in ListView and GridView sample on GitHub.

get checked items of listview using checkbox windows store app c#

I am developing one Windows store application. I have implemented one listview. listview contains image , textblock and checkbox controls. my listview gets the data from internet i have done xml parsing with listview and binded data to listview. i want to get all the data from listview where checkboxes are checked in listview.
my xaml code is:
<ListView Name="display" ItemsSource="{Binding}" SelectionMode="Single"
SelectionChanged="display_SelectionChanged"
ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.HorizontalScrollBarVisibility="Visible"
ItemContainerStyle="{StaticResource ListViewItemStyle12}" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel x:Name="stak2" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Image Source="{Binding Path=Image}" Width="450" Tapped="image_taped" />
<CheckBox Tag="{Binding Path=tag}" Visibility="{Binding Path=visichk}" Height="40" Name="addremove"
HorizontalAlignment="Center" Checked="add_checked" Unchecked="sub_checked" Opacity="0.5"
Background="White" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" >
</CheckBox>
<TextBlock Text="{Binding Image_code}" FontSize="25" Foreground="Gray" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
datasource for listview :
XDocument xmlDoc = XDocument.Parse(responseString);
var Categories = xmlDoc.Descendants("product").ToArray();
List<ProductData> displaylst = new List<ProductData>(); //ProductData is my Class.
foreach (var cat in Categories)
{
string prId = cat.Elements("id_products").Select(r => r.Value).FirstOrDefault();
List<string> Image = cat.Descendants("images").Elements("src").Attributes("largimage").Select(r => r.Value).ToList();
List<string> Image_code = cat.Descendants("images").Elements("src").Select(r => r.LastAttribute.Value).ToList();
int i = 0;
foreach (string img in Image)
{
displaylst.Add(new ProductData { Id = prId, Image = img, Image_code = Image_code[i] });
i++;
}
}
display.ItemsSource = displaylst;
Now on one button click i want to get the data of Product like prId,Image,Image_code where checkbox are checked from listview and put it into the simple list.
how can i did this please help me. thanks in advance.
First let's add a property to your ProductData class
public class ProductData
{
public string Id { get; set; }
public string Image { get; set; }
// I dont know exactly what's in this class
// ... more properties
// Add this one
public bool IsSelected { get; set; }
}
Now that we have a boolean IsSelected in our ProductData class we can know which are selected.
In the second foreach change this line
// Set IsSelected to false by default
displaylst.Add(new ProductData { IsSelected = false, Id = prId, Image = img, Image_code = Image_code[i] });
And bind the "IsChecked" property of your checkbox to IsSelected
<CheckBox IsChecked="{Binding Path=IsSelected}" Tag="{Binding Path=tag}" Visibility="{Binding Path=visichk}" Height="40" Name="addremove"
HorizontalAlignment="Center" Checked="add_checked" Unchecked="sub_checked" Opacity="0.5"
Background="White" VerticalAlignment="Top" Template="{StaticResource CheckboxImageTemplate}" >
With binding when you check one of the checkbox, the associed productData IsSelected property will become "true" automatically.
So now you just have to do a new list and select only ProductData where IsSelected is true:
List<ProductData> listOfSelectedProducts = (from product in displaylst
where product.IsSelected == true
select product).ToList();
Here you go you got a list of ProductData with only selected products.

Can I swap a buttons content databind to a different databind in code?

I cannot find any examples to make me understand how and if I can change the databind in c# at the click of a button on, in my case a toggleswitch, Basically I have 32 buttons in my app and those 32 buttons act the same but need different text with-in them depending on some toggle switches they are currently databinded so the text can be saved and retrieved from local storage but what values it gets depends on the state of these toggle switches.
So I currently have :
<Button x:Name="_ovButton1" Content="{Binding Source={StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}" Margin="2,0,250,0" VerticalAlignment="Top" FontSize="14" Height="72" FontWeight="Bold" MouseLeftButtonUp="_ovButton1_MouseLeftButtonUp" MouseLeftButtonDown="_ovButton1_MouseLeftButtonDown" ClickMode="Hover" Hold="_ovButton1_Hold"/>
and I want when a user changes the state of a toggleswitch to change the
{StaticResource AppSettings}, Path=ovName1_1Value, Mode=TwoWay}
to for example:
{StaticResource AppSettings}, Path=ovName1_2Value, Mode=TwoWay}
but I cannot find any example that shows how to do that in c#
what code do I need to do that?
You can specify the target of databinding in code like this:
MyData myDataObject = new MyData(DateTime.Now);
Binding myBinding = new Binding("MyDataProperty");
myBinding.Source = myDataObject;
myText.SetBinding(TextBlock.TextProperty, myBinding);
See more at http://msdn.microsoft.com/en-us/library/ms742863.aspx
-- Edit Note I don't have access to a WP8 Emulator to test this ---
In the view model it looks like this:
public List<string> Members
{
get { return _Members; }
set { _Members = value; OnPropertyChanged(); }
}
public MainVM()
{
// Simulate Asychronous access, such as to a db.
Task.Run(() =>
{
Thread.Sleep(2000);
Members = new List<string>() {"Alpha", "Beta", "Gamma", "Omega"};
});
}
The code behind on the main page sets the datacontext (shared with all the child controls) as such:
public MainWindow()
{
InitializeComponent();
// Set the windows data context so all controls can have it.
DataContext = new MainVM();
}
The Mainpage Xaml to bind to members is like this
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[0] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[1] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[2] }" />
<Button Height="30"
Width="80"
Margin="10"
DataContext="{Binding Members}"
Content="{Binding Path=[3] }" />
The result is this visually:
I based this on my blog article Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding for more info and a fuller example.
I think your best bet is going to be to use a collection of strings and bind to that collection. You can either change the collection when a toggle is switched, or keep 6 collections and bind to the collection that is for the toggle.
Xaml:
<ItemsControl x:Name="Buttons" ItemsSource="{Binding ButtonTextCollection}">
<ItemsControl.ItemsPanel>
<toolkit:WrapPanel/>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Width="100" Height="70" Content="{Binding}" Click="OnButtonClick"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Your code-behind would have the event handler for your button click
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var text = ((Button) sender).Content.ToString();
// Send the text
}
Your ViewModel would hold the ButtonTextCollection property and would change based on the toggle.
public ICollection<string> ButtonTextCollection
{
get { return _buttonTextCollection; }
set
{
_buttonTextCollection = value;
OnPropertyChanged("ButtonTextCollection");
}
}
When you want to change the text, you would change the ButtonTextCollection
public void ChangeButtonText()
{
ButtonTextCollection = new Collection<string> {"A", "B",...};
}

How to bind data to a ListBox in a ControlTemplate?

What I am trying to do is to create some sort of "rooms"(like a chat group, a sharing center or whatever you want). All the room are created the same way, but each one of them contains different informations. Each of these rooms is contained in a TabItem. I managed to create dynamically all the Tabitems, to give those a Grid and a Canvas. But at the moment I am facing a problem: I created a ControlTemplate Called RoomMenu that will show different buttons and, the most important, the people connected in this room in a ListBox(I retrieve those people from a WebService each time I change the selected Tabitem). But since my ListBox is in a ControlTemplate I have no idea how to access the ListBox ItemSource to bind a generic List to it. Down Below is the code used to create my rooms and their content.
Here is my room menu class:
public class RoomMenu : ContentControl
{
public RoomMenu()
{
DefaultStyleKey = typeof(RoomMenu);
}
public string Current_room_id;
public string FullName;
public string Rights;
}
And here is the ControlTemplate located in generic.xaml:
<Style TargetType="test:RoomMenu">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="test:RoomMenu">
<Grid x:Name="MenuGrid">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Black" CornerRadius="2" Background="Black">
<StackPanel Orientation="Vertical">
<Border x:Name="Room_friend_border" Background="Gray" CornerRadius="4" Margin="5">
<ListBox x:Name="current_room_friends" ItemsSource="{Binding ''}" Margin="5" Height="230">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FullName}" Height="20"/>
<TextBlock Text="{Binding Rights}" Height="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Border x:Name="Room_menu" Background="Gray" CornerRadius="4" Margin="5">
<StackPanel Orientation="Vertical" Margin="10">
<Button Content="Add item" Margin="0,2,0,2"/>
<Button Content="Set changes" Margin="0,2,0,2"/>
<Button Content="Invite friend" Margin="0,2,0,2"/>
<Button Content="Rename room" Margin="0,2,0,2"/>
<Button Content="Delete room" Margin="0,2,0,2"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is my Dictionnary Class that contains the RoomMenu:
public class Rooms : TabItem
{
public string Room_guid;
public string Room_name;
public string Primary_user_guid;
public string Room_version;
public Grid Room_grid;
public Canvas Room_canvas;
public RoomMenu Room_menu;
}
And this is when I call my ControlTemplate and Add it to my TabItem's Grid:
public void Set_rooms_interface()
{
foreach (KeyValuePair<string, Rooms> kvp in rooms_list)
{
rooms_list[kvp.Key].Room_menu = new RoomMenu();
rooms_list[kvp.Key].Room_canvas = new Canvas();
rooms_list[kvp.Key].Room_grid = new Grid();
//instance grid columns
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition() {Width = new GridLength(900)});
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition());
//Refreshing room canvas
rooms_list[kvp.Key].Room_canvas.Height = rooms_list[kvp.Key].Room_grid.ActualHeight;
rooms_list[kvp.Key].Room_canvas.Width = rooms_list[kvp.Key].Room_grid.ActualWidth;
rooms_list[kvp.Key].Room_canvas = refresh_canvas(kvp.Key);
Grid.SetColumn(rooms_list[kvp.Key].Room_canvas, 0);
Grid.SetColumn(rooms_list[kvp.Key].Room_menu, 1);
//Add Canvas to Grid
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_canvas);
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_menu);
//Setting TabItem Name
rooms_list[kvp.Key].Header = rooms_list[kvp.Key].Room_name;
//Adding Grid to TabItem.Content
rooms_list[kvp.Key].Content = rooms_list[kvp.Key].Room_grid;
//Adding TabItem to TabControl
Room_tab.Items.Add(kvp.Value);
}
}
I'm sorry if the whole question is a bit long but it was the only way to explain clearly what I was trying to do. So if anyone could give me a hint or answer to do some databinding in a ControlTemplate it would greatly help me.
Thank You.
I think you started in the wrong direction when instantiating UI elements in code. The code behind should only contain one line assigning the people list to the current_room_friends DataContext.
Start with simpler examples of binding data to a ListBox like the beautiful planet example of Bea Stollnitz.

Categories

Resources