How to unselect a listbox datatemplate item? - c#

<TabItem Name="tbInActive" Header="Previous" Width="100" Height="100">
<ListBox Name="lbActive"
DockPanel.Dock="Top"
ItemContainerStyle="{DynamicResource SelectedItemContainer}">
<ListBox.ItemTemplate>
<DataTemplate >
<EventDet:EventSumDetail x:Name="ItemCtrl"
SelectedItem="{Binding ElementName=lbInActive, Path=SelectedItem}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- ... -->
</TabItem>
In my codebehind I tried
this.lbActive.SelectedItem = null; and this.lbActive.UnselectAll(); and (edit) this.lbActive.SelectedIndex = -1;
But they had no effect.

There is no reason why this.lbActive.SelectedItem = null; should not work. (It works on a clean slate ListBox)
I'm quite sure the problem lies with your custom parts, either SelectedItem="{Binding ElementName=lbInActive, Path=SelectedItem}" is forcing a selection, or a binding in your ItemContainerStyle does so.

I guest that EventDet:EventSumDetail is a kind of ListBoxItem or something like that.
The problem you had a OneWay binding(by default)... you had to explicitly make it TwoWay binding.. like this:
<EventDet:EventSumDetail SelectedItem="{Binding ElementName=lbInActive, Path=SelectedItem, Mode=TwoWay}" />
Also, you don't need to name (x:Name="ItemCtrl"), in this case it's unnecessary.

Related

How to create a template with parameters in WPF?

I have 3 List views. They are very similar. The only difference is that their ItemsSource binds to different variables. Is there a way to create a template list view with unknown ItemsSource, and I can pass a parameter to fill that ItemsSource?
My code is something like this:
<ListView Name="View1" ItemsSource={"Binding Student1"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
<ListView Name="View2" ItemsSource={"Binding Student2"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
<ListView Name="View3" ItemsSource={"Binding Student3"}>
<TextBlock Text={"Binding Name"}/>
</ListView>
Edit:
I might have expressed my question in a wrong way. I would like to have a separate user control view called "StudentView":
<ListView ItemsSource=Parameter1>
<TextBlock Text={"Binding Name"}/>
</ListView>
So that in my main window, I can do something like this:
<local:StudentView Parameter1={"Binding Student1"}/>
You are on the right track with thinking about templating
What you are looking for is something called a ControlTemplate.
Your ControlTemplate would then target the ListView control and use the key word TemplateBinding to pass through the ItemsSource binding from your ListView
You would look to add this as a window resource as shown below.
<Window.Resources>
<ControlTemplate x:Key="ListViewTemplate" TargetType="ListView">
<ListView ItemsSource="{TemplateBinding ItemsSource}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ControlTemplate>
</Window.Resources>
This would enable you to use this template on your ListView controls as shown below
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList}"/>
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList1}"/>
<ListView Template="{StaticResource ListViewTemplate}" ItemsSource="{Binding PersonList2}"/>
Hope this gives you what you were looking for

How to collapse contents of a databound ListBoxItem when a button is clicked in WPF MVVM

I have a ListBox in my WPF MVVM app using the following code:
<GroupBox Grid.Column="0" Margin="0,0,0,-58">
<DockPanel>
<TextBlock DockPanel.Dock="Top"
HorizontalAlignment="Center"
Margin="0,0,0,8"
FontWeight="Bold"
Text="{x:Static p:Resources.AvaliableLEDsLabel}" />
<ListBox Name="AvailableLEDsListbox" SelectionMode="Extended"
dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True"
dd:DragDrop.DropHandler="{Binding}"
ItemTemplate="{StaticResource DataTemplateListBoxItem}"
ItemsSource="{Binding AvailableLeds}"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
>
<ListBox.GroupStyle>
<StaticResource ResourceKey="StyleListBoxGroup" />
</ListBox.GroupStyle>
</ListBox>
</DockPanel>
</GroupBox>
This displays grouped lists of devices, with LEDs under them. The DataTemplate is the following:
<GroupStyle x:Key="StyleListBoxGroup">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Button Command="{Binding HideGroupCommand}">X</Button>
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Left"
FontWeight="Bold"
Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
<DataTemplate x:Key="DataTemplateListBoxItem">
<TextBlock x:Name="LedId" Text="{Binding LedId}"/>
</DataTemplate>
I would like to make the X button in the header hooked up to the HideGroupCommand toggle the hiding of all the items under that particular header. How would I go about doing this? Thanks in advance.
You have few options.
First one :
You would need to have a property in your view model something like 'ListBoxVisibility' then u would bind that property to your UI. In command text u just changed visibility property of that property in view model- so u have it reflected on UI. This visibility property can be of type 'bool' , or 'Visibility' or whatever. Only if it's type of Visibility u don't need converter when binding.
NOTE : Some people use it - even though it kinda goes out of general principel of MVVM patter. But sometimes u have to do it.
Second
If wanna stick to MVVM , then u need to fully separate your UI from your viewmodel. Create click event and change visibility.

Combobox not showing groupings

I'm trying to organize the items in a combobox into groups. To do this I've created an object that has project and group name strings. I then set the GroupStyle and ItemTemplate to display these values. However, Currently, only the project string is displayed in the combobox (and the box has a red border, indicating some kind of error).
Here's the xaml for my combobox:
<ComboBox x:Name="comboBoxProjects" Margin="165,90,28,0" Grid.Column="0" VerticalAlignment="Top" Height="25"
IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Style="{StaticResource ComboBoxDefault}"
ItemsSource="{Binding Path=ProjectClientSelections.ProjectGroupItems,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=ProjectClientSelections.SelectedProject, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding GroupName}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Project}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Does anyone see where I'm going wrong?
In GroupStyle, the DataContext is not your item (the type contained in your ItemsSource), but a CollectionViewGroup object, which is formed based on the collection of items that you have grouped. Because of this you have to declare a binding path to one of the properties in CollectionViewGroup, for example, based on your code you probably want to use Name property. See MSDN CollectionViewGroup Class
Change your GroupStyle.HeaderTemplate to this:
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
You don't show how you have formed your GroupDescriptions. If you have not grouped the items already, you can do it in following way (assuming the XAML you have provided is contained inside Window and Window's and GroupBox's DataContext is the same):
<Window.Resources>
<CollectionViewSource
Source="{Binding ProjectClientSelections.ProjectGroupItems}"
x:Key="GroupedProjectItems">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription
PropertyName="GroupName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
After this change GroupBox ItemSource binding to the following (directly to CollectionViewSource resource):
ItemsSource="{Binding Source={StaticResource GroupedProjectItems}}"

How to (is it possible to) set property of user control from outside?

This is my XAML:
<UserControl x:Class="SearchResultsBox">
<ListBox ItemsSource="{Binding SearchResults}" SelectedItem="{Binding Selected}"
Style="{StaticResource ListBoxStyle1}"
ItemContainerStyle="{StaticResource SearchItemContainerStyle}"
Background="{StaticResource DefaultBackground}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<local:Forecast_SearchResults_ListView_Data/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl x:Class="SearchResultsBox">
I want to be able to reuse this listbox and just slap on a new datatemplate from the external context:
<local:SearchResultsBox>
<DataTemplate = {ForecastDataTemplate}/>
</local>
And it will put this DataTemplate into the ListBox.ItemTemplate property. Is this even possible? If so, how? If not, is there another way to achieve a similar effect?
you may use as follows
<local:SearchResultsBox ItemTemplate="{StaticResource ForecastDataTemplate}" />
and you can wire up the property to the underlying ListBox
eg
add a name to listbox
<ListBox x:Name="list" ... />
add a property wiring
public DataTemplate ItemTemplate
{
get { return list.ItemTemplate;}
set { list.ItemTemplate = value;}
}

Binding a collection to Listbox

I basically started today with WPF, and I'm astounded by how difficult it is to do binding. I have an array of TextBoxes, in an ObservableCollection, and just want to bind that in my Listbox, so that they arrange themselves vertically.
I have fiddled around with this for 3 already, can you help?
I'm working in a WPF UserControl, not a window as so many tutorials seem to rely on.
In your C# code, you can do something like this:
myListBox.ItemsSource = myTextBoxesCollection;
Or in your XAML code:
<ListBox ItemsSource="{Binding MyTextBoxesCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Text}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
For the XAML, MyTextBoxesCollection needs to be a public property on your data context. One way to set the DataContext could be, in your constructor:
DataContext = this;
Having an ObservableCollection<TextBox> is alomost always the wrong approach. You likely want an ObservableCollection<string> instead.
Then, in your ListBox (or ItemsCollection) you have the following code:
<ListBox ItemsSource="{Binding MyStrings}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding .}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Make MyTextBoxCollection (your ObservableCollection of textboxes) a public property of your DataContext.
<ListBox ItemsSource=”{Binding MyTextBoxCollection}”>
<ListBox.ItemTemplate>
<DataTemplate><TextBox Text=”{Binding Text}” /></DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Categories

Resources