I want to display checkboxes alongside text in ListView. I have multiple ListViews in my WPF window, hence I want to specify this behavior as a style in resources. But the checkboxes are not displayed, only the text is. So please, find below my code and suggest edits.
<Window.Resources>
<Style TargetType="ListView" x:Key="ListViewTemplate">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" Content=""></CheckBox>
<Separator Width="5"></Separator>
<TextBlock Text="{Binding Text}"></TextBlock>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ListView Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="8" Grid.RowSpan="5" x:Name="listViewDocTypes" Style="{DynamicResource ListViewTemplate}" >
</ListView>
</Grid>
Provide a Text or Width to the Checkbox. Without setting the Text property the length will automatically be "0" if you do not specify its Width.
<CheckBox Content="xyz" Width="1234"/>
The problem was that I was binding data the wrong way.I was using the following code.
ListViewItem item = new ListViewItem();
item.Tag = docType;
item.Text = docType.Text;
listViewDocTypes.Items.Add(item);
The correct way to bind is
listViewDocTypes.ItemsSource = docTypes;
Related
I have an ItemsControl that contains a textbox for each binding item and I want to allow overlaying text box content if its content is wider than the textbox width similar to excel cells overlaying behavior.
Is there a way to do this?
<ItemsControl ItemsSource="{Binding Path=MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Width="100"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" TextWrapping="WrapWithOverflow"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can use tooltip for that. You just need to bind the source with itself.
<ListView ItemsSource="{Binding Path=MyStringCollection}">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Width="100"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" TextWrapping="WrapWithOverflow" ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
For further information:
DrawToolTip Event
Set ToolTipSize
To replicate a similar behavior, you can make use of a Popup.
To implement a similar behavior, you first must disable content wrapping of your TextBox.
Then replace the current TextBox with a TextBlock, which is used to display the text.
The Popup, which actually contains the editable TextBox, will then overlay this TextBlock at the exact position, thus hiding the TextBlock to make it appear to stretch and overlay the adjacent items.
A MultiTrigger will close the Popup as soon as the focus moved outside the ListBoxItem.
To improve performance you should use the VirtualizingStackPanel as items host.
<ListView ItemsSource="{Binding MyStringCollection}"
HorizontalAlignment="Left"
Width="800">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Border BorderThickness="1"
BorderBrush="Gray">
<TextBlock Text="{Binding}" />
</Border>
<Popup x:Name="EditableTextSiteHost"
PlacementTarget="{Binding ElementName=TextSite}"
Placement="Relative"
Height="{Binding ElementName=TextSite, Path=ActualHeight}"
AllowsTransparency="True"
FocusManager.FocusedElement="{Binding ElementName=EditableTextSite}">
<TextBox x:Name="EditableTextSite"
Text="{Binding TextData}" />
</Popup>
</Grid>
<DataTemplate.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"
Value="True" />
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsKeyboardFocusWithin}"
Value="True" />
</MultiDataTrigger.Conditions>
<Setter TargetName="EditableTextSiteHost"
Property="IsOpen"
Value="True" />
</MultiDataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<!-- Make items overlap -->
<Setter Property="Margin"
Value="-2,0,0,0" />
<Setter Property="Padding"
Value="0" />
<Setter Property="Width"
Value="50" />
<Style.Triggers>
<!-- Apply zero Margin on the first item -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}"
Value="{x:Null}">
<Setter Property="Margin"
Value="0,0,0,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>
To-do
This is just a raw example, a proof of concept. You would have to improve the behavior. For example, you would want to close the Popup when the user scrolls or moves the Window. Otherwise, since Popup itself is a Window, the Popup would not move to follow the placement target. You could move the related logic to an attached behavior.
You likely also want to improve the selection behavior. Currently the selection highlight border does not (virtually) extend to surround the Popup. You have to mimic this by applying a Border on the TextBox that will replicate the ListBoxItem highlight border.
I managed to produce the excel cells overlay behavior by using a Grid with dynamic column count using this helper dependency properties https://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/ as a container template of ItemsControl and binding the column index of each textbox to the ordered item index and binding Grid.ZIndex to the reversed index to be displayed above the adjacent text boxes.
<ItemsControl ItemsSource="{Binding MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid HorizontalAlignment="Left" helpers:GridHelpers.ColumnCount="{Binding MyCollection.Count}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding ItemIndex}"/>
<Setter Property="Grid.ZIndex" Value="{Binding ReversedIndex}" />
<Setter Property="Grid.ColumnSpan" Value="{Binding MaxMergedCells}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBox MinWidth="30" Text="{Binding }"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
I am creating a list of CheckBoxs and a ComboBox that contains the list of checked checkboxes in WPF MVVM application. I don't know how to bind in text of combobox checked values from checkboxes.
Here is what I have tried:
<ComboBox ItemsSource="{Binding Systems}" Grid.Row="4" Grid.Column="1"
IsEditable="True" IsReadOnly="True" Text="{}">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding TemplateName}" IsChecked="{Binding
IsSystemChecked, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
This should do the trick:
<StackPanel>
<ListView ItemsSource="{Binding Systems}" >
<ListView.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding TemplateName}" IsChecked="{Binding
IsSystemChecked, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ComboBox ItemsSource="{Binding Systems}" DisplayMemberPath="TemplateName" >
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSystemChecked}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Setter.Value>
</Setter>
</Style>
</ComboBox.Style>
</ComboBox>
</StackPanel>
Here there is:
ListView containing a checkbox for each item in Systems which is bound to to the IsSystemChecked property
ComboBox containing all of the items in Systems however if the IsSystemChecked property is false the Visibility is set to Collapsed so it is not displayed
Let me know if you have any issues! Hope this helps.
I have a datagrid which has, in the head of every column a combobox. I want a tooltip to appear when hovering the combobox, to show the selected item value
<DataGrid HeadersVisibility="Column" Name="griglia" Grid.Row="2" ItemsSource="{Binding Path=Test}" AutoGenerateColumns="True" IsReadOnly="True" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate DataType="DataGridColumnHeader">
<ComboBox ItemContainerStyle="{StaticResource SingleSelectionComboBoxItem}" DisplayMemberPath="Oggetto" Width="100" Height="20" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.Selezione, UpdateSourceTrigger=LostFocus}" SelectionChanged="SingleSelectionComboBox_SelectionChanged"/>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Content = "what should i put here????"/>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
What should i put inside the content property of the tooltip? I already tried
Content = "{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridColumnHeader}},Path=DataContext.Tot.Oggetto}"
where Tot.Oggetto is a string containing the displayed item in the combobox but it doesn't work
EDIT: I tried already to set tooltip property fo the combobox like
ToolTip="{Binding Path=SelectedItem.ToolTip, RelativeSource={RelativeSource Self}}"
but it does not show any tooltip
Your first try is setting the Tooltip of the DataGridColumnHeader, but it seems you want to set the Tooltip of the ComboBox, right?
You can set the Tooltip of a ComboBox to show its selected value as follows:
<ComboBox ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=SelectedValue}" ...>
RelativeSource={RelativeSource Self} is binding to the ComboBox itself. Then Path=SelectedValue specifies that you want to bind to the property SelectedValue of this ComboBox, instead of binding directly to itself.
So your code would then be: (I erased the code that was setting the Tooltip of the DataGridColumnHeader and modified the code for the ComboBox inside the DataTemplate)
<DataGrid HeadersVisibility="Column" Name="griglia" Grid.Row="2" ItemsSource="{Binding Path=Test}" AutoGenerateColumns="True" IsReadOnly="True" ScrollViewer.CanContentScroll="True" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate DataType="DataGridColumnHeader">
<ComboBox ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=SelectedValue}" ItemContainerStyle="{StaticResource SingleSelectionComboBoxItem}" DisplayMemberPath="Oggetto" Width="100" Height="20" ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},Path=DataContext.Selezione, UpdateSourceTrigger=LostFocus}" SelectionChanged="SingleSelectionComboBox_SelectionChanged"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
I'm using radiobuttons inside a listbox and cannot disable them.
After searching I found links about IsEnabled and IsHitTestVisible. When I set IsEnabled to false the button and text turns grey however it's still clickable. Setting IsHitTestVisible does nothing to change this. My XAMLcode looks like this:
<ListBox ItemsSource="{Binding Source}" BorderThickness="0" VerticalAlignment="Stretch" Background="Transparent" SelectedItem="{Binding SelectedSource, Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" >
<ListBox.ItemTemplate>
<DataTemplate>
<RadioButton IsHitTestVisible="{Binding IsEnabled}" IsEnabled="{Binding IsEnabled}" Margin="0 2 0 0" FontSize="12" FontFamily="Segoe UI Regular" Content="{Binding name}" GroupName="GroupList" >
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="IsChecked" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
</Style>
</RadioButton.Style>
</RadioButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Property in c# that calculates and returns bool.
public bool IsEnabled
{
get
{
IsEnabledCalculate();
return isEnabled;
}
}
Any ideas about how to disable selection?
Using IsHitTestVisible on a RadioButton in ListBox was a good start. This way, when you click the RadioButton, the event goes "through" it and is handled by ListBoxItem (the item gets selected). You can then manipulate IsChecked property by binding it do IsSelected property of the ListBoxItem.
This is however still not enough to achieve waht you want. First, you're binding your IsEnabled property on the wrong level: the RadioButton. As you noticed, this still allows the ListBoxItem to get selected. So, you need to bind your IsEnabled property to the IsEnabled property of ListBoxItm instead:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsEnabled" Value="{Binding Path=IsEnabled}"/>
</Style>
</ListBox.ItemContainerStyle>
There still is one minor issue here. When your IsEnabled property is changed in the codebehind, the ListBoxItem will get disabled but the RadioButton will still be checked. To prevent this and uncheck the RadioButton whenever the item gets disabled you can use a DataTrigger:
<DataTemplate>
<RadioButton GroupName="GroupList" IsHitTestVisible="False"
Margin="0 2 0 0" FontSize="12" FontFamily="Segoe UI Regular"
Content="{Binding name}" >
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="IsChecked" Value="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</RadioButton.Style>
</RadioButton>
</DataTemplate>
i have listbox, and the data template is button :
<ListBox x:Name="lbname" ItemsSource="{Binding myCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button x:Name="btnname" Content="{Binding name}" Click="btnname_Click">
<Button.Background>
<ImageBrush ImageSource="/myApplication;component/images/buttons/normal.png"/>
</Button.Background>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
i have two image backgroud for this listBox image (normal.png for normal mode, click.png for selected item in listBox)
The listBox view items in list of buttons, the button image background is normally normal.png
my question is how to change the button image background to click.png for selected one and the old selected button retrieve to normal.png
How to change image background for selected item in listBox with buttons in each line ?
hope this clear, please i spend about one day about this issue
can any one help
Thanks
I haven't tested it, but you need some code that looks like this:
<ListBox x:Name="lbname" ItemsSource="{Binding myCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<Button x:Name="btnname" Click="btnname_Click">
<Grid>
<Image>
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="/myApplication;component/images/buttons/normal.png" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Value="True">
<Setter Property="Image.Source"
Value="/myApplication;component/images/buttons/click.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding name}" HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The idea is to bind directly to the IsSelected property of the ListBoxItem object. This is done using a RelativeSource binding. However, I'm guessing that this code doesn't do what you want... I suggest that you might want to use a ToggleButton instead... something like this:
<ListBox x:Name="lbname" ItemsSource="{Binding myCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<ToggleButton x:Name="btnname" Click="btnname_Click" IsChecked="{Binding
IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type
ListBoxItem}}}">
<Grid>
<Image>
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="/myApplication;component/images/buttons/normal.png" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}}}"
Value="True">
<Setter Property="Image.Source"
Value="/myApplication;component/images/buttons/click.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<TextBlock Text="{Binding name}" HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ToggleButton>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
if you are using MVVM then make a property in viewModel and bind this to ImageBrush as ImageSource,
when you are selecting value in ListView then get selected record and change image path of this property.
Try using Togglebutton instead of button.Use a trigger to check when the IsChecked property of the toggleButton changes. And based on that change your image.