How to remove or add an item from a WrapPanel? - wpf

I am trying to create a prototype where the user can show or display items by selecting the menu items. I need the item to be removed/Collapsed because I need the empty space to be taken by other items in WrapPanel. The content in the wrapPanel is generated dynamically with XMLDataProvider. I tried to assign commands for the menu items but was not able to make it work.
XAML:
<Grid Margin="20">
<Menu x:Name="Manage_Menu" HorizontalAlignment="Left" Background="{x:Null}" ScrollViewer.VerticalScrollBarVisibility="Auto" Foreground="#FF2A2A2A" Margin="0,0,0,5" >
<MenuItem Header="Show/Hide">
<MenuItem Header="1" Command="{x:Static local:MainWindow.FirstThumbVisibilityWindowCommand}" IsCheckable="true" IsChecked="True"/>
<MenuItem Header="2" Command="{x:Static local:MainWindow.FirstThumbVisibilityWindowCommand}" IsCheckable="true" />
<MenuItem Header="3" Command="{x:Static local:MainWindow.FirstThumbVisibilityWindowCommand}" IsCheckable="true" />
<MenuItem Header="4" Command="{x:Static local:MainWindow.FirstThumbVisibilityWindowCommand}" IsCheckable="true" />
<MenuItem Header="5" Command="{x:Static local:MainWindow.FirstThumbVisibilityWindowCommand}" IsCheckable="true" />
</MenuItem>
</Menu>
<Frame Content="Frame" Source="../tiles.xaml" NavigationUIVisibility="Hidden" />
</Grid>
I hope someone will be able to help.
The whole solution is available from here:
http://cid-0c29483cf3a6a14d.office.live.com/self.aspx/WPF%5E_Tests/DragDropWrapPanel%5E_3.rar
Please take a look. You will find Menu on top left corner that should be used to hide/show items inside the wrapPanel.
Thank you in advance.

One way to add or remove items from a wrap panel is use a ListBox with the ItemsPanel configured as a WrapPanel
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
Bind the ListBox to an ObservableCollection and then add and remove your view models from the bound collection.

Here is an example of changing the visibility of WrapPanel items from code.
Some sample XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Content="0" Click="Button_Click"/>
<Button Content="1" Click="Button_Click"/>
<Button Content="2" Click="Button_Click"/>
</StackPanel>
<WrapPanel Grid.Row="1" x:Name="wrapPanel">
<Rectangle Fill="Red" Width="100" Height="100"/>
<Rectangle Fill="Green" Width="100" Height="100"/>
<Rectangle Fill="Blue" Width="100" Height="100"/>
</WrapPanel>
</Grid>
and the button event handler:
private void Button_Click(object sender, RoutedEventArgs e)
{
int index = int.Parse((string)((sender as Button).Content));
var child = this.wrapPanel.Children[index];
child.Visibility = child.Visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
}
which just toggles the visibility of the child corresponding to the text on the button.

Here is a quick-n-dirty version that is XAML only. It uses the built-in BooleanToVisibilityConverter, and Element binding.
<Window x:Class="WrapPanelHideItems.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WrapPanelHideItems" Height="300" Width="300">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="boolToVis" />
</Window.Resources>
<StackPanel>
<Menu>
<MenuItem Header="Show/Hide">
<MenuItem x:Name="mnuItemOne"
IsCheckable="True"
IsChecked="True"
Header="Show Item One" />
<MenuItem x:Name="mnuItemTwo"
IsCheckable="True"
IsChecked="True"
Header="Show Item Two" />
<MenuItem x:Name="mnuItemThree"
IsCheckable="True"
IsChecked="True"
Header="Show Item Three" />
<MenuItem x:Name="mnuItemFour"
IsCheckable="True"
IsChecked="True"
Header="Show Item Four" />
<MenuItem x:Name="mnuItemFive"
IsCheckable="True"
IsChecked="True"
Header="Show Item Five" />
</MenuItem>
</Menu>
<WrapPanel Orientation="Horizontal"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Gray">
<TextBlock Text="Item One"
Margin="5"
FontSize="25"
Foreground="Red"
Visibility="{Binding ElementName=mnuItemOne, Path=IsChecked,
Converter={StaticResource boolToVis}}"/>
<TextBlock Text="Item Two"
Margin="5"
FontSize="25"
Foreground="Blue"
Visibility="{Binding ElementName=mnuItemTwo, Path=IsChecked,
Converter={StaticResource boolToVis}}"/>
<TextBlock Text="Item Three"
Margin="5"
FontSize="25"
Foreground="Green"
Visibility="{Binding ElementName=mnuItemThree, Path=IsChecked,
Converter={StaticResource boolToVis}}"/>
<TextBlock Text="Item Four"
Margin="5"
FontSize="25"
Foreground="Yellow"
Visibility="{Binding ElementName=mnuItemFour, Path=IsChecked,
Converter={StaticResource boolToVis}}"/>
<TextBlock Text="Item Five"
Margin="5"
FontSize="25"
Foreground="Violet"
Visibility="{Binding ElementName=mnuItemFive, Path=IsChecked,
Converter={StaticResource boolToVis}}"/>
</WrapPanel>
</StackPanel>
</Window>
Of course, in a real-world app, you'd want to use things like Styles and perhaps DataBinding, but this shows that you don't have to be complex to get the results you want. Simpler is usually better.

Related

WPF listboxitem contextmenu

I'm trying to create a ContextMenu for a ListBox. It just should be displayed when a ListBoxItem is selected by a right mouse button click. But the ContextMenu opens whenever a right click is done in that ListBox, even when it's empty.
This is my code:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<ListBox Name="listIn"
Width="148"
Height="175"
Margin="25,52,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
ItemsSource="{Binding Path=groupid}"
SelectionChanged="listBox1_SelectionChanged"
SelectionMode="Extended" />
<ListBox Name="listOut"
Width="148"
Height="175"
Margin="335,52,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
MouseRightButtonDown="ListBoxItem_MouseRightButtonDown"
SelectedItem="listBox2_SelectionChanged"
SelectionChanged="listBox2_SelectionChanged"
SelectionMode="Extended">
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="update" />
<MenuItem Header="delete" />
</ContextMenu>
</ListBox.ContextMenu>
</ListBox>
<Button Name="cmdRein"
Width="75"
Height="23"
Margin="215,75,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Click="button1_Click"
Content="moveRight" />
<Button Name="cmdRaus"
Width="75"
Height="23"
Margin="217,0,0,145"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
Click="button2_Click"
Content="moveLeft" />
<Button Name="button1"
Width="59"
Height="23"
Margin="0,14,330,0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Click="button1_Click_1"
Content="Load" />
<TextBox Name="textBox1"
Width="83"
Height="23"
Margin="25,15,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
TextChanged="textBox1_TextChanged" />
</Grid>
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Item 1"/>
<MenuItem Header="Item 2"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Here your Adding ContextMenu for ListBox. This ContextMenu will opens when you right click on the Listbox itself.. If you need the ContextMenu for ListBoxItem alone, initialize ContextMenu for ListBoxItem.
You can define an ItemTemplate for the ListBox like:
<ListBox ItemsSource="{Binding Items, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Item 1"/>
<MenuItem Header="Item 2"/>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The ItemsSource Item is an ObservableCollection<string>

MenuItem Highlight Stays After MouseLeave

I have this menuitem inside of a combobox:
<MenuItem Name="CurrencySelectMenuItem" Header="Currency" Width="Auto"
Background="Black" Foreground="White" BorderThickness="0" Margin="0"
BorderBrush="Black" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
When I highlight the item, it does what I want: it pops up the way it should to display it's children, and highlights to show that it's focused. However, when the mouse leaves, the menuitem stays highlighted, even after clicking some other part of my application.
I tried setting the IsFocused property but it is read only.
Can someone point me in the right direction please?
EDIT (code added):
<Grid>
<ComboBox Name="SettingsCmbx" Text="Options" Foreground="White" VerticalContentAlignment="Center" HorizontalContentAlignment="Stretch" Width="80" Style="{StaticResource blackGradientComboBox}" Margin="3">
<ComboBox.ItemsSource>
<CompositeCollection>
<!--<ComboBoxItem Name="Options" IsEnabled="False" Style="{StaticResource blackComboBoxItem}">Options</ComboBoxItem>-->
<ComboBoxItem Style="{StaticResource blackComboBoxItem}">Guidelines</ComboBoxItem>
<ComboBoxItem Style="{StaticResource blackComboBoxItem}">Copy Investigation</ComboBoxItem>
<MenuItem Name="CurrencySelectMenuItem" Header="Currency" Background="Black" Foreground="White" BorderThickness="0" Margin="0" BorderBrush="Black" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<MenuItem Name="DollarSelectMenuItem" Header="_$ - Dollar" Background="Black" Foreground="White"></MenuItem>
<MenuItem Name="PoundSelectMenuItem" Header="_£ - Pound" Background="Black" Foreground="White"></MenuItem>
</MenuItem>
<ComboBoxItem Style="{StaticResource blackComboBoxItem}">About</ComboBoxItem>
</CompositeCollection>
</ComboBox.ItemsSource>
</ComboBox>
<TextBlock Name="OptionsTxtBlk" Text="Options" IsHitTestVisible="False" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
Here's the image:

WPF Control to emulate Outlook Attachment-View

I'm trying to get the ListView to look like the MS Outlook Attachment-Control. I've already got the horizontal scrolling, but it still displays only one item in a row.
How can I get it to look like this?
What I've achieved so far:
<Grid x:Name="grdAttachments"
Grid.Row="4"
Grid.Column="1"
Grid.ColumnSpan="3">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" MaxHeight="45" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="65" />
<ColumnDefinition Width="15" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Margin="3,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Cursor="Hand"
Text="Angefügt:" />
<ScrollViewer Grid.Row="0" Grid.Column="2">
<ListBox x:Name="libAttachments"
Background="Transparent"
ItemsSource="{Binding Attachments}"
MouseDoubleClick="lvAttachments_MouseDoubleClick">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<Image Source="{Binding MimeTypeIcon}" Stretch="None" />
<TextBlock Margin="5,0,0,0" Text="{Binding File.Name}" />
<StackPanel.ContextMenu>
<ContextMenu>
<ContextMenu.Items>
<MenuItem Click="btnOpenAttachment_Click" Header="Öffnen">
<MenuItem.Icon>
<Image Source="/Images/magnifier.png" Stretch="None" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Click="btnSaveAttachment_Click" Header="Speichern unter">
<MenuItem.Icon>
<Image Source="/Images/disk-black.png" Stretch="None" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu.Items>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
</Grid>
It sounds like what you want is an ListBox with a custom ItemsPanel.
<ListBox>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
The snippet above configures a ListBox to use a WrapPanel as the layout provider or "ItemsPanel" for the items it is to present. From there it may make sense to implement a custom Item Container style, and/or custom Data Templates. You could easily apply a DataTemplate as you did above if you are using an MVVM pattern and data binding to a collection (preferably observable)
<DataTemplate>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<Image Source="{Binding MimeTypeIcon}" Stretch="None" />
<TextBlock Margin="5,0,0,0" Text="{Binding File.Name}" />
</StackPanel>
</DataTemplate>
To complete this picture, a scroll viewer can be used so long as it's height is constrained by either a parent layout control (Grid.Row = 1 where RowDefinition Height="constant") or my an explicit height being set on the ScrollViewer.
My final solution based on yours looks like this:
<ScrollViewer HorizontalScrollBarVisibility="Disabled">
<ListBox
ItemsSource="{Binding Attachments}"
MouseDoubleClick="lvAttachments_MouseDoubleClick"
SelectionMode="Single">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,10,0" Orientation="Horizontal">
<Image Source="{Binding MimeTypeIcon}" Stretch="None" />
<TextBlock Margin="5,0,0,0" Text="{Binding File.Name}" />
<StackPanel.ContextMenu>
<ContextMenu>
<ContextMenu.Items>
<MenuItem Click="btnOpenAttachment_Click" Header="Öffnen">
<MenuItem.Icon>
<Image Source="/Images/magnifier.png" Stretch="None" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Click="btnSaveAttachment_Click" Header="Speichern unter">
<MenuItem.Icon>
<Image Source="/Images/disk-black.png" Stretch="None" />
</MenuItem.Icon>
</MenuItem>
</ContextMenu.Items>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</ScrollViewer>
A few things to note: When possible, consider using Commands instead of events, they can lead to looser coupling. Introducing a Behavior might even make sense if the behavior it's self is something that you might have other places in your project or re-usability is ideal.
Ok so where it seems you got snagged up was with your ListBox still pushing things in single column fashion and the lack of ability to give you something to fire off say a click event. So what I had in mind was something more like this;
<ScrollViewer HorizontalScrollBarVisibility="Disabled" Height="300" HorizontalContentAlignment="Stretch">
<ItemsControl ItemsSource="{Binding Collection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Margin="5,0" Orientation="Horizontal">
<Image Source="{Binding MimeTypeIcon}" Stretch="None" />
<HyperlinkButton Margin="5,0,0,0" Text="{Binding File.Name}" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
I wasn't to sure what you were trying to do with your magnifier and disk though I see your Clicks for them, but you can add those to this layout however you like, just a note though, I just free-handed this between meetings so never built it but should work fine. If not we'll plug at it again. Main differences are changing to a hyperlinkbutton to give you click and some other subtle differences from Firoso's but his is still technically sound, or should be anyway :)

ScrollViewer Actual Height Returning Incorrect Value?

No matter what I do I cant make the line extent to the bottom of the scrollview :(
<Grid>
<DockPanel
HorizontalAlignment="Stretch"
Name="dock"
VerticalAlignment="Stretch"
LastChildFill="True"
Focusable="True">
<Menu
Name="menuBar"
HorizontalContentAlignment="Stretch"
BorderThickness="0,0,0,1"
BorderBrush="Silver"
VerticalAlignment="Top"
DockPanel.Dock="Top">
<MenuItem
Header="File" />
<MenuItem
Header="Options">
<MenuItem
Header="Personal Info" />
</MenuItem>
<MenuItem
Header="View" />
<MenuItem
Header="About" />
</Menu>
<TextBox
Name="txtInput"
DockPanel.Dock="Bottom"
Height="23"
SpellCheck.IsEnabled="True"
VerticalAlignment="Bottom"
BorderThickness="1,2,1,1"
KeyDown="txtInput_KeyDown"
TabIndex="1" />
<ListBox
Name="lstUsers"
ItemsSource="{Binding}"
DockPanel.Dock="Right"
Width="160"
BorderThickness="2,0,0,0"
BorderBrush="LightGray" />
<ScrollViewer
Name="lstMessagesScroll"
VerticalScrollBarVisibility="Auto">
<ItemsControl
Name="lstMessages"
ItemsSource="{Binding}"
VerticalAlignment="Bottom" />
</ScrollViewer>
</DockPanel>
<Line
StrokeThickness="0.5"
X1="116"
X2="116"
Y1="23"
Stroke="Gainsboro"
Y2="{Binding ElementName=lstMessagesScroll, Path=ActualHeight}" />
</Grid>
Any tips?
In playing around with your XAML I found that if you bind the Height to same element and set Y1 to 0 it will act the way that I believe you are expecting.
<Line
StrokeThickness="0.5"
X1="116"
X2="116"
Y1="0"
Stroke="Gainsboro"
Y2="{Binding ElementName=lstMessagesScroll, Path=ActualHeight }"
Height="{Binding ElementName=lstMessagesScroll, Path=ActualHeight }" />
It's working correctly - it's just that you are not taking the Menu into the account.

Can I use a DataTemplate for toolbar buttons and still make the name meaningful?

I have a Toolbar whose ItemSource is a collection of toolbarItems which contain the bitmap text and other info for the button and the xaml includes a DataTemplate to bind the data to the button.
Our app now needs to become 508 compliant and when I run the Accessible Event Watcher it is listing all the toolbar button names as "Unknown".
Can someone tell me how to provide a meaningful name to the buttons?
Here's the portion of xaml applying to this issue:
<ToolBar.ItemTemplate>
<DataTemplate DataType="{x:Type src:toolBarItem}">
<DataTemplate.Resources>
<src:toolBarItemConverter x:Key="buttonConverter" />
<src:booleanToVisibilityConverter x:Key="boolToVisibilityConverter" />
<src:toolBarButtonFormatConverter x:Key="toolBarFormatDisplayConverter" />
<src:stringToVisibilityConverter x:Key="stringToVisibilityDisplayConverter" />
</DataTemplate.Resources>
<StackPanel Orientation="Horizontal">
<Border Style="{StaticResource SeparatorStyle}" Visibility="{Binding menuSeparator, Converter={StaticResource boolToVisibilityConverter}}"/>
<Button x:Name="listButton" Height="{Binding menuHeight, Mode=OneWay}" Width="{Binding menuWidth}" VerticalAlignment="Top" HorizontalAlignment="Center" Visibility="{Binding isActiveButton, Converter={StaticResource boolToVisibilityConverter}}" Tag="{Binding}"
ToolTip="{Binding menuTooltip}" IsEnabled="{Binding isEnabled}" >
<UniformGrid VerticalAlignment="Center" HorizontalAlignment="Center" Rows="{Binding menuText,Converter={StaticResource toolBarFormatDisplayConverter}}" >
<!-- button image -->
<Image Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center" Source="{Binding menuImage, Converter={StaticResource buttonConverter}}"/>
<!-- button name -->
<Viewbox StretchDirection="DownOnly" HorizontalAlignment="Center" VerticalAlignment="Bottom" Visibility="{Binding menuText, Converter={StaticResource stringToVisibilityDisplayConverter}}" >
<TextBlock x:Name="buttonName" FontFamily="Segoe UI" Width="{Binding menuWidth}" FontSize="12" Grid.Row="1" TextAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Center" VerticalAlignment="Bottom" Text="{Binding menuText}" Foreground="Black" />
</Viewbox>
</UniformGrid>
<!-- </StackPanel> -->
</Button>
</StackPanel>
</DataTemplate>
</ToolBar.ItemTemplate>
Thanks,
Ron
OK we figured this out. Need to simply bind your names to the AutomationProperties.Name
<Button x:Name="listButton" AutomationProperties.Name="{Binding menuText}"
Height="{Binding menuHeight, Mode=OneWay}" Width="{Binding menuWidth}"
VerticalAlignment="Top" HorizontalAlignment="Center"
Visibility="{Binding isActiveButton,
Converter={StaticResource boolToVisibilityConverter}}"
Tag="{Binding}" ToolTip="{Binding menuTooltip}" IsEnabled="{Binding isEnabled}" >

Resources