I have a Grid inside a ListBox bound to a list of items. When I press a global 'edit' button, I want a series of checkboxes to appear in the Grid. I was planning on doing this in a similar fashion to how orientation change is handled, however I can't figure out how to access the bound grid to change the column properties
Here's my XAML:
<ListBox ItemsSource="{Binding Path=Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<CheckBox
Grid.Column="0"
Grid.ColumnSpan="1"
IsChecked="{Binding IsSelected, Mode=TwoWay}">
</CheckBox>
<TextBlock
Grid.Column="0"
Grid.ColumnSpan="3"
Text="{Binding ItemName}">
</TextBlock>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I was going to set the CheckBox and TextBlock ColumnSpan to 2 on edit mode, then back to 1/3 on cancel. But I can't access those.
Is there a smarter way to do this?
I also considered setting visibility on the Checkbox to a bound value, but this will mean the grid will still have a gap when not in edit mode.
Related
In my WPF application I have ListBox which contains a collection of items. One item can be added when a button is clicked and it is selected in the opened dialogue. As soon as a item is selected the dialogue closes and the item's image and name should be displayed in my ListBox. Unfortunately the Listbox does not update and nothing changes.
Usercontrol with Listbox:
<ListBox ItemsSource="{Binding BlButtonCollection, UpdateSourceTrigger=PropertyChanged}" VerticalContentAlignment="Stretch" SelectedItem="{Binding SelectedSticker}"
HorizontalContentAlignment="Stretch" ItemContainerStyle="{StaticResource ListBoxItemStyle}">
<ListBox.Resources>
<viewmodels1:BindingProxy x:Key="ProxyElement" Data="{Binding}" />
</ListBox.Resources>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="4" Rows="10"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Grid x:Name="f">
<Grid.RowDefinitions>
<RowDefinition Height="5*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnSelectArticle" Background="Transparent" Grid.RowSpan="2" BorderThickness="0"
Command="{Binding DataContext.ButtonClicked,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBox}}}"/>
<Image Height="1.5cm" HorizontalAlignment="Center" Source="{Binding ItemImage.ImageUrl, Converter={StaticResource ImageFormatConverter}}"/>
<TextBlock Text="{Binding ItemName}" Width="4cm" Height="0.8cm" TextWrapping="Wrap" Grid.Row="1" HorizontalAlignment="Center"/>
</Grid>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Controls with ListBoxes in main window:
<formats:OneXTwo x:Name="oneXTwo" BlButtonCollection="{Binding BlButtons_2}" IsBlVisible="Visible" Visibility="{Binding Are2StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:ThreeXEight x:Name="threeXEight" BlButtonCollection="{Binding BlButtons_24}" IsBlVisible="Visible" Visibility="{Binding Are24StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}"/>
<formats:FourXTen x:Name="fourXTen" BlButtonCollection="{Binding BlButtons_40, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" IsBlVisible="Visible" Visibility="{Binding Are40StickersVisible}"
ButtonClicked="{Binding BlStickerButtonClickedCommand}" SelectedSticker="{Binding SelectedBlSticker, Mode=TwoWay}" />
I should mention that I have three different formats and each format is a own user-control. Therfore, they are displayed in a shell-view and based on a ComboBox selection one format is displayed. If I am running the application, select a image nothing happens, but if I change the bound value of the textblock in the list view and switch it back to 'Itemname' the Image and Name are displayed.
Have you set the DataContext to a specific ViewModel?
ObservableCollection can only ensure the add/remove operation for items that can be updated to the UI. If you want to the item property to notify the UI, you should override the setter of the property and implement INotifyPropertyChanged.
I am facing a trouble in getting item's index in Listview. I have a child element inside data template like the following:
<ListView x:Name="ptype_gw" Width="300" HorizontalAlignment="Left" ItemsSource="{Binding PropertyTypes}" >
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Text="{Binding title}" Style="{ThemeResource menu_heading_green}" Grid.Row="0" />
<GridView Grid.Row="1" ItemsSource="{Binding childs}" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<RadioButton Name="PropertyTypeRadio" Content="{Binding title}" Tag="{Binding}" GroupName="Types" Checked="RadioButton_Checked" Background="White" Foreground="Black" BorderBrush="Black" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Now i Need to get the index of selected item whenever radio button is checked. I have tried the following code:
var item = (sender as FrameworkElement).DataContext;
int index = ptype_gw.Items.IndexOf(item);
But it didn't helped me.
That’s very simple.
Bind the SelectedItem of list to a property in view model. Say SelectedItem. When user selects an item, the SelectedItem property will hold the details of current selected item.
Now handle the radio button checked or unchecked event as per your requirement. When the event occurs, check the SelectedItem property.
I am talking about MVVM case.
If you are writing code in your xaml.cs itself, then get the selected property of listbox directly like this in the radio button checked event.
ListBoxName.SelectedItem
ListBoxName.SelectedIndex
I have a simple ListBox with about 500 ListBox item. I have 2 comboboxes on one item.
My problem is: When I scroll down I lose all SelectedItem binding data.
I have tried to replace the Virtualizingstackpanel to Stackpanel, but than it eats all of my computer's RAM. So I need to get it work with Virtualizingstackpanel.
The question is:
How can I bind selected items to Comboboxes they are on listboxItems?
the code:
<DataTemplate x:Key="MyViewTemplate6">
<Grid Height="110" Width="480" Margin="10" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ComboBox HorizontalAlignment="Left" VerticalAlignment="Top" Width="120" ItemTemplate="{StaticResource TypeTemplate7}" ItemsSource="{Binding Types}" SelectedItem="{Binding Type, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</Grid>
</DataTemplate>
This is in my ItemTemplate in ListBox.
I have a ListBox set up with automatic numbering as shown below. I want to format the number out front of each ListBoxItem so the numbers in all the rows are right aligned with each other. I figured I could use the item count to determine how many characters are in the index, using that info to set up a format in my viewmodel, and bind to it. Unfortunately I have not even figured out how to format a constant field width for my numbers. The ListBox will look a lot nicer with the contents lined up. So I need to know how to set up the format so I can bind to it.
<ListBox ItemsSource="{Binding Profiles}" SelectedItem="{Binding SelectedProfile, Mode=TwoWay}"
AlternationCount="{Binding Path=Profiles.Count}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Margin="0,0,5,0"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplatedParent.(ItemsControl.AlternationIndex)}"/>
<TextBlock Text="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Your Profile type should have an Index property of some sort, which you should set. AlternationCount "enables alternating containers to have a unique appearance," so I believe you're not using that correctly. When you have that property added to your Profile type then you can do something for your ItemTemplate like:
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100">
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock HorizontalAlignment="Right"
Margin="0 0 5 0"
Grid.Column="0"
Text="{Binding Index}"/>
<TextBlock Grid.Column="1"
Text="{Binding}" />
</Grid>
</DataTemplate>
I have a ListBox control that has been assigned to Grid.Column 0 which has a value of '*' defined for it's width, however when rendered there is a sizeable amount of space that is not being used.
I have also noticed that there is a border of sorts around the ListBox control itself, however I have not added one within the markup.
My UI (Areas of concern marked in Red):
My Markup:
<Window.Resources>
<DataTemplate x:Key="GameImagesTemplate" >
<StackPanel Orientation="Vertical">
<Image Source="{Binding FileInfo.FullName}" Margin="8,8,8,8" Height="70" Width="70" />
<Label Content="{Binding Name}" Width="70" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="GameTemplate">
<StackPanel>
<Label Content="{Binding Name}" Background="Gray" FontSize="16" />
<ListBox x:Name="imageContent" ItemsSource="{Binding FileList}" ItemTemplate="{StaticResource GameImagesTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ListBox x:Name="ContentList" ItemTemplate="{StaticResource GameTemplate}" Grid.Column="0" ScrollViewer.HorizontalScrollBarVisibility="Disabled" />
<StackPanel Grid.Column="1" Background="DarkGray">
<Button Click="OnLoad">_Load</Button>
<Button Click="OnSave">_Save</Button>
<Button Click="OnAdd">_Add</Button>
<Button Click="OnDelete">_Delete</Button>
</StackPanel>
</Grid>
How would I go about resolving both of the issues raised. Is it the default behaviour of the ListBox control?
Many thanks
Yes, that is the default behavior.
In the case of the alignment it looks like you have a WrapPanel in each ListBoxItem which doesn't have quite enough space to put another item on line 1. The remaining space is unused because of the HorizontalContentAlignment setting on ListBox defaulting to Left. This setting is in turn bound to by the default ListBoxItem. Setting HorizontalContentAlignment="Stretch" on your ListBox should fix that.
The outer border comes from the default setting for BorderBrush and BorderThickness. Setting BorderThickness="0" will get rid of it entirely.
There are some other default Padding settings that add some spacing in the default Styles and Templates. If you want to get more into those add a ListBox to a project in Blend and make a copy of its default Template and ItemContainerStyle and check out the XAML. Also consider using the base ItemsControl in cases where you don't need selection behavior, as it doesn't have any of these type of default settings.