How to align the columns of an ItemsControl control (WPF) - c#

I have defined a ItemsControl control in xaml as follows:
<ItemsControl BorderThickness="0" Name="SummaryList">
</ItemsControl>
In the same xaml file, I've defined the following DateTemplate for each item in the ItemsControl:
<DataTemplate DataType="{x:Type app:UpgradeItem}">
<StackPanel Orientation="Horizontal">
<Label Margin="5,5" Content="{Binding Path=ItemText,Mode=OneTime}" />
<Label Margin="5,5" Content="{Binding Path=FromVersion,Mode=OneTime}" />
<Label Margin="5,5" Content="{Binding Path=ToVersion,Mode=OneTime}" />
</StackPanel>
</DataTemplate>
I have bound the ItemsControl's ItemSource to a generlic list of UpgradeItems (i.e. List) and programmatically add to this list during execution. The items in the ItemsControl control populate correctly except that the data in the columns are not aligned. How can I modify this so that the three separate columns (ItemText, FromVersion and ToVersion) are aligned?
TIA

You should be able to use a SharedSize groups on grids, however I feel there is a better way to do this. Here's a link on the subject: http://blogs.microsoft.co.il/blogs/guy/archive/2009/06/30/wpf-grid-shared-size-groups.aspx

Part of what makes this tricky is that the ItemsControl doesn't have "columns": the control itself has no idea how its items' contents are laid out in relation to each other.
Your best bet would probably be to use one of the subclasses of ItemsControl that does support columnar data, such as ListView/GridView or the full-fledged DataGrid.

Related

Adding custom items to stackpanel

I'm working on a project (for Windows Phone 8 with Visual Studio 2012 with C#) where I want to display some items that each have:
a picture
a title
a description
to be able to be clicked (so that I can navigate to a certain Page)
So I thought I could do that with a stackpanel. But I'm not sure how I can add items that have the above properties and to be able to add those items from XAML. I tired adding items through a ItemsControl in stackpanel but I'm not sure how I can add more complex items like the one I want.
The best approach is to use a ListBox or LongListSelector rather than a StackPanel. You can then:
Data bind the list to the control itself, which will handle adding/deleting items from the control automatically
Define the view for each control using ListBox's ItemTemplate property
First of all, in your code-behind/ViewModel/what-have-you, you'll want to create an ObservableCollection of objects to display. ObservableCollection will let the control know to update in the case an item is added, removed, etc.
public ObservableCollection<T> foo = new ObservableCollection<T>();
In XAML, you'll then want to databind this ObservableCollection to the ListBox you've created:
<ListBox x:Name="ListBox" ItemsSource="{Binding foo}" />
Finally, you can define the ItemTemplate of the ListBox like so:
<ListBox x:Name="ListBox" ItemsSource="{Binding foo}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Margin="2">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Description}" />
<Image Source="{Binding Image}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I'd highly recommend reading this guide, especially "Binding a control to a collection of objects" and the section after on DataTemplates. :)

Is there a way to bind to the UIElement children in an ItemsControl?

Let's say I have a simple ItemsControl, bound to a list of simple data objects:
<ItemsControl ItemsSource="{Binding dataModelCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Red" Width="10" Height="10"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The children for the ItemsControl here, are the items in dataModelCollection, and these are simple model types. The Items control, however, will fill itself out with a bunch of Rectangles. Is there a way to bind to these rectangles, and not the data objects?
My assumption is that I can, since when an ItemsControl uses ItemsSource, it locks the Items property from being interfered with - you can't add other elements outside the ItemsSource. However, I have been searching for such a way, and have found nothing.
EDIT: This might look like a silly question, but the reason I am looking for an answer on this, is because I would like to use the ItemsControl to generate some UIElements for each item in dataModelCollection, and then put them on a Panel; I can't put them in the Panel directly, and I can't define the Panel as the ItemsControl.ItemsPanel because I need a reference to the actual Panel for some code-behind purposes.
Please keep my reasons mentioned above in mind when reading my following example of my desired outcome:
<ItemsControl x:Name=elementWrapper ItemsSource="{Binding dataModelCollection}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle Fill="Red" Width="10" Height="10"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<CustomControls:SpecialPanel x:Name="desiredHome" Elements="{Binding ElementName=elementWrapper, Path=ItemContainerGenerator.Items}" />

Binding expanders and listview to nested dictionary

I have a collection that looks like this:
ObservableDictionary<string, ObservableDictionary<string, SystemStatusItem>> ObservableColoServerStatus
I am working on creating a user control that I would like to bind as follows:
Each key (string) key from the outer dictionary should dynamically create an expander.
Inside that expander is a ListView/DataGrid/some control for displaying a collection of information
Each line in the ListView/DataGrid or whatever will be composed of a combination of the (string) Key and a property from the (object)Value of the inner dictionary.
Ideally it should look and operate similarly to a TreeView however Expanders have been widely used through our UI so I would like to stick to this for consistency.
I am new to WPF and have done a bit of basic data binding before but the nature of this nested relationship is making this really difficult to wrap my head around
Ok, first lets asume that you ObservableDictionary is a collection of items that have a Key property and a Value property. What you want can be done in wpf using data templates, please see this code, try do it in this way:
<ListBox ItemsSource="{Binding ObservableColoServerStatus}">
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Key}">
<ListBox ItemsSource="{Binding Value}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Key}"/>
<TextBlock Text="{Binding Value}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It is a list box, that has as ItemsSource your ObservableDictionary, then in the item template property you set the template that will use for representing all it itmes. In this case an expander, that have in the header the key a list box that take the elements from the Value of the first dictionary, and then you have set the template again. It is similar. Hope it works for you...

How to draw a border around each element in ItemsControl?

I'm using an ItemsControl and a ItemTemplateSelector to draw display the UI of my items. But now, all my elements need to be inside in a Grid (and one of its columns the element should be there).
At the beginning I supposed was right to have a ContentControl nested in an ItemsControl, and this ContentControl should have the ItemTemplateSelector, but I'm not sure if this is the best way to do it.
Stuff like that should be in the Template of the item container, for ItemsControls that is a bit problematic as the containers are ContentPresenters which have no Template. You could subclass ItemsControl to use a ContentControl, then use the ItemsControl.ItemContainerStyle to edit the Template of those containers.
<ItemsControl x:Name="lst">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="10" CornerRadius="1" BorderBrush="Navy">
<TextBox Text="{Binding Name}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I hope this will help.

WPF Binding Treeview element to a UserControl

I have a tree view that is using the Model View architecture, each TreeViewItem has a windows Form attribute, when I click on a node I want the application to display the form associated with that node to the right hand side of the tree.
How can you achieve this using binding I have tried the following but the user control Associated with ApplicationForms doesn't get displayed.
<ContentControl Margin="163,5,127,5" Content="{Binding SelectedItem,ElementName=ApplicationTree}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:ApplicationViewModel}">
<StackPanel>
<TextBlock Text="Displaying an A!" />
<ContentPresenter Name="MyContent">
<ContentPresenter.Content>
<UserControl x:Name="UserCntrl2" HorizontalAlignment="Stretch" Height="Auto" Width="Auto" Content="{Binding ApplicationForms}"/>
</ContentPresenter.Content>
</ContentPresenter>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:ApplicationsViewModel}">
<StackPanel>
<TextBlock Text="Displaying a B!" />
<!--<TextBlock Text="{Binding Bar}" />-->
</StackPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
Since you're using MVVM, you can alternativly put that kind of logic in the view model. you can then bind the IsSelected property of tree node to your viewmodel, then when IsSelected get set to true by wpf (when the use selects the item) you can do whatever you want.
Its a very useful pattern to use view models this way. your viewmodels can have references to all kinds of stuff and affect them based on selection or expansion. You can also go the other way around and have code affect the viewmodels and let the databinding update the actual controls
Here is a pretty good article on MVVM and treeview
You should also check out the HierarchicalDataTemplate if you're working with treeviews
-edit-
After reading the question properly, i see that you're already doing the right thing, that is binding your master control to the SelectedItem of the Treeview. I do belive the SelectedItem property points to the TreeViewItem though, not the actual VM. Perhaps thats the problem?

Categories

Resources