Hide items in a ListBox when ListBox is disabled - c#

When a standard ListBox is disabled, the elements in it are simply grayed out. They are still visible, despite not being clickable. I would like to know if it is possible, and if it is, how to hide these items when the ListBox is disabled. I do not want to remove the elements from the ItemSource or create a temp storage for them.
So far, I thought about changing the visibility of the ListBox but that gets rid of the entire thing (including the border lines).

You could bind Visibility of ListBoxItem to IsEnabled of ListBox
<ListBox ItemsSource="{Binding DataSource}">
<ListBox.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</ListBox.Resources>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Visibility" Value="{Binding IsEnabled, RelativeSource={RelativeSource AncestorType=ListBox}, Converter={StaticResource BooleanToVisibilityConverter}}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>

Just add another ListBox to the form and when you disable the first listbox with the elements inside of it, hide it, and then display the other to the user which will essentially be an empty greyed out listbox.
Then when you enable the box back, hide the empty one and show the real one.
Hope this helps.

Related

WPF datagrid how to get access to the row click

Seems that a WPF application I inherited has a DataGrid
<DataGrid x:Name="dataGrid" ItemsSource="{Binding AllTroubleCalls}" SelectedIndex="{Binding SelectedIndex}"
I want to end up setting the Background color to yellow only if the Textbox contains text in it.
The text appears when I click on certain rows in the Datagrid
It seems that everything is based upon this "Binding"
{Binding ... }
I have a textbox that I added a Name to it
<TextBox ToolTipService.ShowDuration="120000" ToolTip="{Binding ThreatText}" Name="txtThreat" Text="{Binding ThreatText}"
TextWrapping="Wrap" AcceptsReturn="True"
VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Visible"
Margin="3" Grid.Row="8" Grid.Column="1"
Grid.ColumnSpan="3" Grid.RowSpan="1" IsReadOnly="True" Height="30"/>
Show then when I am in a method I can "test" this and it works
txtThreat.Background = new SolidColorBrush(Colors.Yellow);
However, I'm not understanding why I cannot get a handle on the data changing from whatever row is clicked on in the Datagrid, that data then appears "magically" in many textboxes etc.. on the xaml page.
I gather that the "Binding" is handling this, but it is also MVVM 2 way binding ?
I have tried plastering so many breakpoints into so many methods but I can't seem to get any of them to show me how the data is changing on row click
There's a little too much going on in this question without the details. However, I can at least answer what I think is your goal. The easiest way to get a textbox to be yellow if there's a text in it is with a style:
<TextBox >
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Background" Value="Yellow"></Setter>
<Style.Triggers>
<Trigger Property="Text" Value="">
<Setter Property="Background" Value="White"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
As for figuring out how the data is changing... The Text displayed in your TextBox is bound to ThreatText. That means the text should change only when a property named ThreatText is changed in a class somewhere (your viewmodel). Have you tried putting a breakpoint on the setter for the ThreatText property? You can also put a breakpoint on the getter as well. It sounds like that when you click in the textbox/row, WPF updates the text in the UI, which means it's reevaluating the binding due to some change in ThreatText; this also means it'll hit the getter... you can check out the stack trace if it does to see what's going on.

ListView.SelectedItems does not change when clicking a TextBox in the ItemTemplate

I have a ListView bound with an ObservableCollection. The Itemtemplate of the ListView is the following:
<ListView ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" PreviewMouseLeftButtonUp="ListViewClicked" PreviewKeyDown="NameBox_KeyDown">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="./Resources/DeleteIcon.png"/>
<TextBox Text="{Binding Path=Name}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This way I give the user the choice to either change the name of the element, or delete it from the list. I handle this two operations in code behind through the two event handlers attached to the ListView.
The problem is that when I click on the TextBox, the SelectedItems property of the ListView doesn't change and it points the last selected item. When I click on the image or on the free space around the selection change.
Now I have two questions:
Is there an easy way to fix this behavior?
Is it possible to get a reference to the collection item whose property is exposed by the TextBox?
One way to deal with this problem is to set Trigger to set IsSelected when keyboard focus is within ListViewItem
<ListView ... SelectionMode="Single">
<!-- .... -->
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
</ListView>

How to change font size in a WPF combobox for its popup only

In my WPF application I have a ComboBox. What I try to do is, to set a different font size on the popup only. The display of the selected item within the collapsed ComboBox should remain as it currently is.
Although I dismantled the whole thing to item templates and control templates in my XAML, I did not yet succeed to size only the popup's text...
Maybe one of you could give me the right point for doing so.
You can change ItemContainerStyle for ComboBoxItem
<ComboBox ...>
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="FontSize" Value="20"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
this should affect only items in the popup

Highlight (select) DataGridRow based on object property in Silverlight

For context, I'm looking to replicate the FeatureDataGrid implemented by ESRI for a map visualization app. Using MVVM, I have bound the map and data to an observable collection of DataPoints. Each DataPoint has an IsSelected property, which is toggled when you change the associated checkbox in the datagrid, or if you click the map graphic that represents it.
I'd like to remove the IsSelected CheckBoxColumn from the datagrid, and instead change the IsSelected property of a DataPoint by simply selecting it in the datagrid.
Selecting something in the datagrid would change IsSelected, which should be reflected on the map automatically by a change in color/size of the graphic. Conversely, selecting objects in the map should make them highlighted in the datagrid.
Is this possible? Where should I begin?
Here are some attempts that did not work:
<sdk:DataGrid x:Name="datagrid" HorizontalAlignment="Left" Width="400" ItemsSource="{Binding Path=Data, Mode=TwoWay}">
<sdk:DataGrid.RowStyle>
<Style TargetType="sdk:DataGridRow">
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
</Style>
</sdk:DataGrid.RowStyle>
</sdk:DataGrid>
and
<sdk:DataGrid x:Name="datagrid" HorizontalAlignment="Left" Width="400" ItemsSource="{Binding Path=Data, Mode=TwoWay}" SelectedItem="{Binding IsSelected, Mode=TwoWay}"/>
To be clear, the map is bound to the collection and isn't an important part of this question--I'm simply looking for a way to bind the IsSelected property of a DataPoint to the DataGridRow's highlighted/selected state.
Let me know if more information would be useful.
EDIT
I've found a solution that I believe violates MVVM and adds some (hopefully) unnecessary logic. Perhaps someone more knowledgable with MVVM could comment and convince me otherwise, or confirm my inclination:
Putting this in the code behind:
public MainPage()
{
InitializeComponent();
Messenger.Default.Register<DataPointSelectedMessage>(this, DataPointSelectedChange);
}
private void DataPointSelectedChange(DataPointSelectedMessage msg)
{
if (datagrid.SelectedItems.Contains(msg.Content))
{
datagrid.SelectedItems.Remove(msg.Content);
}
else
{
datagrid.SelectedItems.Add(msg.Content);
}
}
EDIT 2
I'm still new to silverlight. Turns out ListBox does the behavior I'm looking for by default. Here is the related code for anyone who runs into this:
<ListBox ItemsSource="{Binding Path=Data, Mode=TwoWay}" SelectionMode="Multiple">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I would still be interested to get input on implementing this with a datagrid, however. I may end up needing some datagrid features.
Thanks.

WPF listbox. Skip underscore symbols in strings

I have some WPF ListBox which is dynamically populating with items. Something like this :
ListBox.Items.Add
(new ListBoxItem { Content = new CheckBox { IsChecked = true, Content = "string_string"} );
The problem is with checkbox content. It's showing on GUI like "stringstring"...
How to escape the "_" symbols ? (I get strings dynamically)
You can add the text in a TextBlock and put that TextBlock inside your Chekbox, TextBlock does not support _ mnemonic characters. Here's what I mean, in xaml, but you can easily convert this to code:
<CheckBox IsChecked="True">
<TextBlock>string_string</TextBlock>
</CheckBox>
The default template for the CheckBox contains a ContentPresenter whose RecognizesAccessKey is set to true. If the content is a string (which it is in your case), then the ContentPresenter creates an AccessText element to display the text. That element hides the underscore until the Alt key is pressed because it will treat it as a mnemonic. You can either retemplate the CheckBox such that its ContentPresenter's RecognizesAccessKey is false or better yet just provide a DataTemplate as the ContentTemplate which contains a TextBlock. If you're not sure if the content will be a string then you can set the ContentTemplateSelector and in code provide a DataTemplate which contains a TextBlock only if the item is a string. e.g.
<ListBox xmlns:sys="clr-namespace:System;assembly=mscorlib">
<ListBox.Resources>
<DataTemplate DataType="sys:String" x:Key="stringTemplate">
<TextBlock Text="{Binding}" />
</DataTemplate>
<Style TargetType="CheckBox">
<Setter Property="ContentTemplate" Value="{StaticResource stringTemplate}" />
</Style>
</ListBox.Resources>
<ListBoxItem>
<CheckBox Content="A_B" ContentTemplate="{StaticResource stringTemplate}"/>
<!-- Or use the implicit style to set the ContentTemplate -->
<CheckBox Content="A_B" />
</ListBoxItem>
</ListBox>
Use a double underscore string__string, since in WPF, the _ is the mnemonic character.
Even better, just solve this issue in xaml and create a collection in your view model (or code-behind).
I had the same problem in a DataGrid. Similarly to AndrewS, I added a style for TextBlock, but did not use DataTemplate or ContentTemplate. This way the setters in ColumnHeaderStyle were applied :) However, this solution works only for single underscores, eg. "a_b", but not for "a__b".
<DataGrid>
<DataGrid.Resources>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="{Binding}"/>
</Style>
</DataGrid.Resources>
<DataGrid.ColumnHeaderStyle>
<!-- my setters here do not get overridden -->
</DataGrid.ColumnHeaderStyle>
</DataGrid>

Categories

Resources