How to set VerticalContentAlignment to top in WrapPanel? - c#

I have a WrapPanel which is vertically aligned.
My problem is, whenever an elements overflows, it goes to next column. So the items in First column becomes uniformly aligned vertically.
Example: Suppose I have 170px Height for WrapPanel and 35px Height for items of WrapPanel. So it will show first 4 elements in first column which will be uniformly spaced. Rest items will be transferred to next column and so on. In the 170px height, I want these items to use their required height and leave the extra space as it is. So after 140px, I should get 30px space free.
I am not getting any way to do this from the properties of WrapPanel, As it is having very less properties to support the layout and styling of its items.
How can I do this?

You could use a VariableSizedWrapGrid, just like from the Contoso Cookbook Windows 8 examples. State a MaximumRowsOrColumns there, and it will wrap your items onto another column (or row).
<VariableSizedWrapGrid Orientation="Vertical"
MaximumRowsOrColumns="4" />
Is this what you want?

Here is a example of using UniformGrid that may be close to what you are trying to achieve.
XAML
<Grid>
<ListBox ItemsSource="{Binding GridItemsList}" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Rows="2" Columns="4" FlowDirection="RightToLeft" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding ItemName}" />
<StackPanel.LayoutTransform>
<RotateTransform Angle="-90"/>
</StackPanel.LayoutTransform>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.LayoutTransform>
<RotateTransform Angle="-90"/>
</ListBox.LayoutTransform>
</ListBox>
</Grid>
Code Behind
public partial class UniformGridWindow : Window {
public UniformGridWindow() {
//Sample Data
GridItemsList = new List<GridItem> {
new GridItem("Item 1"),
new GridItem("Item 2"),
new GridItem("Item 3"),
new GridItem("Item 4"),
new GridItem("Item 5"),
new GridItem("Item 6"),
new GridItem("Item 7"),
new GridItem("Item 8")
};
InitializeComponent();
this.DataContext = this;
}
public List<GridItem> GridItemsList { get; set; }
}
public class GridItem {
public string ItemName { get; set; }
public GridItem(string itemName) {
this.ItemName = itemName;
}
}

Related

Draw variable number of rectangles within WPF Grid cells?

I have a WPF Grid which is 3 columns wide and 8 rows:
<Window x:Class="Container.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="700" Width="1000">
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*" />
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10*" />
</Grid.ColumnDefinitions>
</Grid>
</Window>
I am using this to draw something like this:
Every cell in the first and third columns may have a different number of rectangles. Also, the width of each rectangle may be different and change at run-time. The width will be proportionate to a number (known at run-time and continually-changing).
What is the best way to draw these rectangles?
Here is what I've come up with after about an hour of fiddling (GitHub Repo):
I'm using the MVVM pattern to make the UI as easy as possible. Right now, it just populates with some random data.
The XAML:
<Window
x:Class="BuySellOrders.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:BuySellOrders"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
mc:Ignorable="d">
<Window.DataContext>
<local:MainWindowVm />
</Window.DataContext>
<Grid Margin="15">
<ItemsControl ItemsSource="{Binding Path=Prices}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:PriceEntryVm}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border
Grid.Column="0"
Padding="5"
HorizontalAlignment="Stretch"
BorderBrush="Black"
BorderThickness="1">
<ItemsControl HorizontalAlignment="Right" ItemsSource="{Binding Path=BuyOrders}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:OrderVm}">
<Border
Width="{Binding Path=Qty}"
Margin="5"
Background="red"
BorderBrush="Black"
BorderThickness="1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<Border
Grid.Column="1"
BorderBrush="Black"
BorderThickness="1">
<TextBlock
Margin="8"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="{Binding Path=Price}" />
</Border>
<Border
Grid.Column="2"
Padding="5"
BorderBrush="Black"
BorderThickness="1">
<ItemsControl ItemsSource="{Binding Path=SellOrders}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:OrderVm}">
<Border
Width="{Binding Path=Qty}"
Margin="5"
Background="red"
BorderBrush="Black"
BorderThickness="1" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
The view models:
class MainWindowVm : ViewModel
{
public MainWindowVm()
{
var rnd = new Random();
Prices = new ObservableCollection<PriceEntryVm>();
for (int i = 0; i < 8; i++)
{
var entry = new PriceEntryVm();
Prices.Add(entry);
entry.BuyOrders.CollectionChanged += OnOrderChanged;
entry.SellOrders.CollectionChanged += OnOrderChanged;
entry.Price = (decimal)110.91 + (decimal)i / 100;
var numBuy = rnd.Next(5);
for (int orderIndex = 0; orderIndex < numBuy; orderIndex++)
{
var order = new OrderVm();
order.Qty = rnd.Next(70) + 5;
entry.BuyOrders.Add(order);
}
var numSell = rnd.Next(5);
for (int orderIOndex = 0; orderIOndex < numSell; orderIOndex++)
{
var order = new OrderVm();
order.Qty = rnd.Next(70) + 5;
entry.SellOrders.Add(order);
}
}
}
private void OnOrderChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (var item in e.NewItems)
{
var order = item as OrderVm;
if (order.Qty > LargestOrder)
{
LargestOrder = order.Qty;
}
}
}
}
private int _largestOrder;
public int LargestOrder
{
get { return _largestOrder; }
private set { SetValue(ref _largestOrder, value); }
}
public ObservableCollection<PriceEntryVm> Prices { get; }
}
public class PriceEntryVm: ViewModel
{
public PriceEntryVm()
{
BuyOrders = new OrderList(this);
SellOrders = new OrderList(this);
}
private Decimal _price;
public Decimal Price
{
get {return _price;}
set {SetValue(ref _price, value);}
}
public OrderList BuyOrders { get; }
public OrderList SellOrders { get; }
}
public class OrderList : ObservableCollection<OrderVm>
{
public OrderList(PriceEntryVm priceEntry)
{
PriceEntry = priceEntry;
}
public PriceEntryVm PriceEntry { get; }
}
public class OrderVm : ViewModel
{
private int _qty;
public int Qty
{
get { return _qty; }
set { SetValue(ref _qty, value); }
}
}
I had to make some assumptions about the naming of things, but hopefully you should get the basic idea of what's going on.
It's structured as a list of PriceEntry, each of which contains a Price, and a BuyOrders and SellOrders properties.
BuyOrders and SellOrders are just lists of orders that have a Quantity property.
The XAML binds the list of price entries to a template that contains a 3 column grid. The first and 3rd columns of that grid bound to another set of item controls for each list of orders. The template for each order is just a border with a Width bound to the Quantity of the order.
All the binds means that just updating a property, or adding an order to either the buy or sell list of a price entry will automatically propagate to the UI. Adding or removing a PriceEntry will also automatically adjust the UI.
I haven't implemented your automatic scaling yet, but the basic idea would be to use a ValueConverter on the Quantity binding, to make it automatically adjust to the largest order.
As an extra note, it uses this nuget package to provide some of the MVVM boiler-plate code, but you should be able to use anything you want, as long as it gives you INotifyPropertyChanged support.
Here is a bonus screen capture showing the dynamic nature of MVVM updating the UI based on a timer.
This only needed a few lines of code to randomly pick a row, then randomly pick an order on the row, then add or subtract a small random amount from the quantity.
_updateTimer = new DispatcherTimer();
_updateTimer.Tick += OnUpdate;
_updateTimer.Interval = TimeSpan.FromSeconds(0.01);
_updateTimer.Start();
private void OnUpdate(object sender, EventArgs e)
{
var entryIndex = _rnd.Next(Prices.Count);
var entry = Prices[entryIndex];
OrderList list;
list = _rnd.Next(2) == 1 ?
entry.BuyOrders :
entry.SellOrders;
if (list.Any())
{
var order = list[_rnd.Next(list.Count)];
order.Qty += _rnd.Next(0, 8) - 4;
}
}
Right then, here goes....
This is exactly the kind of thing you want to use data-binding for. You can try and do things manually if you like, but your code will quickly become very messy if you do. WPF lets you do things the old-school way (i.e. similar to WinForms et al) but that was really to facilitate porting of legacy code. I won't go into too much detail about MVVM (plenty of info on the net about it), but you can get started by using NuGet to add MVVMLightLibs or some other MVVM framework to your project and then you assign your main window a view model by doing something like this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
}
So now it's time for the view model itself, which is a model of the data structures that you want your view to display:
public class MainViewModel : ViewModelBase
{
public ObservableCollection<PriceLevel> PriceLevels { get; } = new ObservableCollection<PriceLevel>
{
new PriceLevel(110.98, new int[]{ }, new int[]{ }),
new PriceLevel(110.97, new int[]{ }, new int[]{ }),
new PriceLevel(110.96, new int[]{ }, new int[]{ }),
new PriceLevel(110.95, new int[]{ }, new int[]{ 5 }),
new PriceLevel(110.94, new int[]{ }, new int[]{ 3, 8 }),
new PriceLevel(110.93, new int[]{ 8, 3, 5, }, new int[]{ }),
new PriceLevel(110.92, new int[]{ 3 }, new int[]{ }),
new PriceLevel(110.91, new int[]{ }, new int[]{ }),
};
}
public class PriceLevel
{
public double Price { get; }
public ObservableCollection<int> BuyOrders { get; }
public ObservableCollection<int> SellOrders { get; }
public PriceLevel(double price, IEnumerable<int> buyOrders, IEnumerable<int> sellOrders)
{
this.Price = price;
this.BuyOrders = new ObservableCollection<int>(buyOrders);
this.SellOrders = new ObservableCollection<int>(sellOrders);
}
}
If you don't already know, ObservableCollection is very similar to list but it propegrates change notification, so when you make your view display the data in it your GUI will update automatically whenever the list changes. This MainViewModel class contains an ObservableCollection of type PriceLevel, and each PriceLevel contains the price and the lists of buy and sell orders. This means you'll be able to add and remove price points, and also add and remove the orders in the price points, and your front-end will reflect those changes.
So on to the front end itself:
<Window.Resources>
<!-- Style to display order list as horizontal list of red rectangles -->
<Style x:Key="OrderListStyle" TargetType="{x:Type ItemsControl}">
<!-- Set ItemsPanel to a horizontal StackPanel -->
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<!-- Display each item in the order list as a red rectangle and scale x by 8*size -->
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1" Margin="5" >
<Rectangle Width="{Binding}" Height="20" Fill="Red">
<Rectangle.LayoutTransform>
<ScaleTransform ScaleX="8" ScaleY="1" />
</Rectangle.LayoutTransform>
</Rectangle>
</Border>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Style to make Price cells vertically aligned -->
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- This style centers the column's header text -->
<Style TargetType="DataGridColumnHeader">
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</Window.Resources>
<!-- This datagrid displays the main list of PriceLevels -->
<DataGrid ItemsSource="{Binding PriceLevels}" AutoGenerateColumns="False" IsReadOnly="True"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False"
CanUserResizeRows="False" CanUserSortColumns="False" RowHeight="30">
<DataGrid.Columns>
<!-- The buy orders column -->
<DataGridTemplateColumn Header="Buy orders" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding BuyOrders}" Style="{StaticResource OrderListStyle}" HorizontalAlignment="Right" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<!-- The price column -->
<DataGridTextColumn Header="Price" Width="Auto" Binding="{Binding Price}" />
<!-- The sell orders column -->
<DataGridTemplateColumn Header="Sell Orders" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding SellOrders}" Style="{StaticResource OrderListStyle}" HorizontalAlignment="Left" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Looks a bit full-on, but if you break it down into sections it's actually pretty straightforward. The main different between this and what you've been trying to do is that I'm using a DataGrid. This is basically a Grid control that's had extra functionality added to make it respond dynamically to data that it's been bound to. It also has a lot of extra stuff we dont' need (editing, column resize/reordering etc) so I've turned all that off. The DataGrid binds to PriceLevels in the view model, so it will display a vertical list showing each one. I've then explicitly declared the 3 columns you're after. The middle one is easy, it's just text, so DataGridTextColumn will, do the job. The other two are horizontal arrays of rectangles, so I've used DataGridTemplateColumn which allows me to customize exactly how they look. This customization is mostly done in the OrderListStyle at the very top of the XAML which sets ItemsPanel to a horizontal StackPanel and sets ItemTemplate to a rectangle. There's also a bit of XAML in there to scale the rectangle by a constant, according to the value of the integer it's displaying in the order list.
Here's the result:
I know the XAML might seem a little full-on, but keep in mind this is now fully data-bound to that view model and it will automatically update in response to changes. This little bit of extra work at the start results in MUCH cleaner update code which is also easier to test and debug.
Hope this is what you're after, if you have any questions let me know and we can take it into chat.
UPDATE: If you want to see the dynamic update in action then add this to your main view model's constructor, it just adds and removes orders randomly:
public MainViewModel()
{
var rng = new Random();
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(0.1);
timer.Tick += (s, e) =>
{
var row = this.PriceLevels[rng.Next(this.PriceLevels.Count())]; // get random row
switch (rng.Next(4))
{
case 0: row.BuyOrders.Add(1 + rng.Next(5)); break;
case 1: row.SellOrders.Add(1 + rng.Next(5)); break;
case 2: if (row.BuyOrders.Count() > 0) row.BuyOrders.RemoveAt(rng.Next(row.BuyOrders.Count())); break;
case 3: if (row.SellOrders.Count() > 0) row.SellOrders.RemoveAt(rng.Next(row.SellOrders.Count())); break;
}
};
timer.Start();
}

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.

how to change the image style received from webservice in windows phone 7

I am sharing the screen shot of my application. The image which is coming i want it to be in the side and should be small in size. Here i am not getting the full image also. Can anyone help me to fit the image in the listbox and appear it in the side.
My xaml code is:
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<Button>
<Button.Content>
<ScrollViewer HorizontalScrollBarVisibility="Auto" Height="80" Width="400">
<!--<ScrollViewer Height="80">-->
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<StackPanel Orientation="Vertical" Height="80">
<TextBlock Text="{Binding Path=News_Title}" TextWrapping="Wrap" ></TextBlock>
<TextBlock Text="{Binding Path=News_Description}" TextWrapping="Wrap"></TextBlock>
<TextBlock Text="{Binding Path=Date_Start}" TextWrapping="Wrap"></TextBlock>
<Image Source="{Binding ImageBind }" />
</StackPanel>
</StackPanel>
</ScrollViewer>
</Button.Content>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
My .cs code is:
public class Newss
{
public string News_Title { get; set; }
public string News_Description { get; set; }
public string Date_Start { get; set; }
public string image_path { get; set; }
public BitmapImage ImageBind{get;set;}
}
public News()
{
InitializeComponent();
KejriwalService.aapSoapClient client = new KejriwalService.aapSoapClient();
client.getarvindNewsCompleted += new EventHandler<KejriwalService.getarvindNewsCompletedEventArgs>(client_getarvindNewsCompleted);
client.getarvindNewsAsync();
}
void client_getarvindNewsCompleted(object sender, KejriwalService.getarvindNewsCompletedEventArgs e)
{
string result = e.Result.ToString();
List<Newss> listData = new List<Newss>();
XDocument doc = XDocument.Parse(result);
foreach (var location in doc.Descendants("UserDetails"))
{
Newss data = new Newss();
data.News_Title = location.Element("News_Title").Value;
//data.News_Description = location.Element("News_Description").Value;
data.Date_Start = location.Element("Date_Start").Value;
data.image_path = location.Element("image_path").Value;
data.ImageBind = new BitmapImage(new Uri( #"http://political-leader.vzons.com/ArvindKejriwal/images/uploaded/"+data.image_path, UriKind.Absolute));
listData.Add(data);
}
listBox1.ItemsSource = listData;
}
Try to move your Image outside inner StackPanel :
.....
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<StackPanel Orientation="Vertical" Height="80">
<TextBlock Text="{Binding Path=News_Title}" TextWrapping="Wrap" ></TextBlock>
<TextBlock Text="{Binding Path=News_Description}" TextWrapping="Wrap"></TextBlock>
<TextBlock Text="{Binding Path=Date_Start}" TextWrapping="Wrap"></TextBlock>
</StackPanel>
<Image Source="{Binding ImageBind }" />
</StackPanel>
.....
That will make the Image appear besides the Text. Then try to set Width and Height properties of Image control to fixed value, and set Stretch property appropriately. See this post for reference about setting Stretch property.
There're too many wrong things here, and I don't know what you want.
You've put buttons inside items of ListBox. You should either remove buttons and rely on listbox own items selection mechanism for handling touch elents, or continue using buttons but replace ListBox with ItemsControl that doesn’t handle touch.
You’ve put ScrollViewer inside those buttons. So if you have 10 items, you’ll have 10 buttons, each with its own scroll viewer. Why you did that?
You’ve set height of your StackPanel to 80. When specifying fixed height, Silverlight often does not care whether the content fits or no, instead it clips things. It’s rarely a good idea to specify absolute size of elements.
Instead of using two nested stack panels, you should use single Grid with two rows and two columns, where image occupies both rows of the second column (using Grid.RowSpan property).
And you’re asking question about changing image style? You should fix the rest of your XAML first…

Can't change gridview itemssource

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;

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