Displaying Content only when ListViewItem is Selected
I have a ListBox
when one of the ListBoxItems
are selected I want to change the visibility of the button "View" and display it. Meaning that the default state is Hidden.
Is this possible and if so, do I solve this with a trigger in XAML or in code behind?
XAML Piece
<ListBox Background="Transparent"
ItemContainerStyle="{StaticResource listBoxTemplate}" BorderThickness="0">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Beige" Margin="10 10 10 10"
HorizontalAlignment="Center" Width="500" Height="100"
VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Name="TopRow" Height="50" />
开发者_如何学C <RowDefinition Name="BottomRow" Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Name="LeftSideMenu" Width="*"/>
<ColumnDefinition Name="Middle" Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="{Binding name}" />
<Button Grid.Column="1" VerticalAlignment="Center"
Grid.RowSpan="2" Name="view" Click="viewClicked_Click"
Grid.Row="0">View</Button>
<Label Grid.Column="0" Grid.Row="1"
Content="{Binding description}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
[Old useless code]
EDIT:
Well I didn't read the question good enough but this should do the trick:
Replace the button in your DataTemplate
with this:
<Button Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" VerticalAlignment="Center"
Name="view" Click="viewClicked_Click"
Content="View">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListBoxItem}},Path=IsSelected}"
Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
What happends here is that the style sets the Visibility property to Collapsed and uses a trigger to change that. I've used a DataTrigger
so you can use the {Binding ...}
.
With the {Binding RelativeSource={..}}
you can look for an Ancestor, here we are looking for an Ancestor of type ListBoxItem
.
What this does is look 'up' in the WPF tree to see if this button has a Parent object which is of type ListBoxItem
if it's found it will check the IsSelected (Path=IsSelected
) property if it's True and will then update the Visibility Property of the button.
I hope this explanation makes sense! :-)
EDIT2: Just for fun, the code behind way:
private Button _previousButton;
private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (_previousButton != null)
_previousButton.Visibility = Visibility.Collapsed;
// Make sure an item is selected
if (listBox.SelectedItems.Count == 0)
return;
// Get the first SelectedItem (use a List<object> when
// the SelectionMode is set to Multiple)
object selectedItem = listBox.SelectedItems[0];
// Get the ListBoxItem from the ContainerGenerator
ListBoxItem listBoxItem = listBox.ItemContainerGenerator.ContainerFromItem(selectedItem) as ListBoxItem;
if (listBoxItem == null)
return;
// Find a button in the WPF Tree
Button button = FindDescendant<Button>(listBoxItem);
if (button == null)
return;
button.Visibility = Visibility.Visible;
_previousButton = button;
}
/// <summary>
/// Finds the descendant of a dependency object.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">The obj.</param>
/// <returns></returns>
public static T FindDescendant<T>(DependencyObject obj) where T : DependencyObject
{
// Check if this object is the specified type
if (obj is T)
return obj as T;
// Check for children
int childrenCount = VisualTreeHelper.GetChildrenCount(obj);
if (childrenCount < 1)
return null;
// First check all the children
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child is T)
return child as T;
}
// Then check the childrens children
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = FindDescendant<T>(VisualTreeHelper.GetChild(obj, i));
if (child != null && child is T)
return child as T;
}
return null;
}
I suggest you use the XAML Trigger "way" because it's much cleaner...
Use a converter on the selected item on the list to determine the visibility.
<Button Visibility="{Binding ElementName=lb, Path=SelectedItem, Converter={StaticResource TestConverter}}" />
Here is the value converter
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
else
return Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
If you're using the MVVM pattern, you should bind your button to an ICommand such as the DelegateCommand from the MVVM Toolkit. That way the button will use the command's CanExecute() state to decide for itself whether it should be enabled or not.
精彩评论