I want to bind a command to a comboboxitem much like a typical command (either application or custom) is bound to a button. I can't seem to find an example.
EDIT:
The ComboBoxItem exists as part of a ContentControl that also contains a button. The button has an associated command that works well. How can I bind a command, in a similar way, to the ComboBoxItem?
<!-- Line -->
<Button x:Name="Line"
Style="{DynamicResource Button_Title}"
Grid.Row="1"
Grid.RowSpan="3"
Grid.Column="0"
Content="Line"
Command="{x:Static local:Ribbon_AC.Custom_RoutedUICommand}"
CommandParameter="Line"
Tag="{DynamicResource Line_32}"/>
<!-- Arc -->
<ContentControl x:Name="ArcSplit"
Template="{DynamicResource Control_SplitSmall}"
Tag="{DynamicResource Arc_20}"
Grid.Row="1"
Grid.Column="1">
<ComboBox Name="ComboBox_Arc"
Style="{DynamicResource ComboBox_Small}"
Width="{DynamicResource Width_DropDown}">
<!-- Arc_0 -->
<ComboBoxItem x:Name="Arc_0"
Style="{DynamicResource ComboBoxItem_Large}"
Tag="{DynamicResource Arc0_32}"
Content="Arc 0">
</ComboBoxItem>
<ComboBox>
<ComboBox.Resources>
<Style TargetType="ComboBoxItem">
<EventSetter Event="Foo" Handler="Bar"/>
</Style>
</ComboBox.Resources>
</ComboBox>
As one of the options you can consider putting a Button into the ComboBox's ItemTemplate and change the Button's template to make it look "not like a button at all".
But that is dirty. Maybe you can use Menu instead of ComboBox?
Related
I have an ItemsControl which displays a list of messages. It's defined as ...
<ItemsControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
ItemsSource="{Binding Messages}" >
</ItemsControl>
I then have a DataTemplate which handles the display for each message. It's defined as...
<DataTemplate DataType="{x:Type vm:MessageViewModel}">
<Button Command="{Binding CommandOpenPage}">
<Button.Template>
<ControlTemplate>
<Border Margin="2" BorderThickness="1"
BorderBrush="{Binding Flags, Converter={StaticResource msgFlagConverter}}"
Background="{Binding Flags, Converter={StaticResource msgFlagConverter}, ConverterParameter=1}" >
<TextBlock Text="{Binding Path=Message}" Style="{StaticResource ActionItem}" TextWrapping="Wrap" />
</Border>
</ControlTemplate>
</Button.Template>
</Button>
</DataTemplate>
Everything displays OK. My problem is when the parent controls are set to Visibility=Collapsed my ItemsControl still goes through the DataTemplate and calls the converters for BorderBrush and BackgroundBrush for each MessageViewModel.
This is bothersome because when the list is very large the bindings are set and converters are executed when they shouldn't. This list is only visible when the user chooses to see it. I understood the binding engine ignores elements under a collapsed parent. Is there an exception to this rule? Or am I just missing something?
I found my problem. The above ItemsControl and DataTemplate were in a UserControl. The visibility was originally handled inside the usercontrol itself by binding the main layout grid to a visibility property. By simply setting the user controls visibility in the parent XAML all bindings started behaving as expected.
This fixes my problem but I still don't understand the difference between setting the visibility of the main layout grid vs the visibility of the usercontrol itself.
<c:ApplicationMenuView Grid.Column="1" Grid.Row="4"
HorizontalAlignment="Left" Margin="1"
VerticalAlignment="Stretch"
DataContext="{Binding Menu}"
Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"/>
The application I'm developing has a kind of accordion made of expanders but each exapnder acts independently rather than only allowing a single open item at a time. Each expander is related to an item in a collection in the view model.
My currently solution is to use a listbox and then bind the lists itemsource to the collection and have an item template render the expander and the exapnders contents.
The problem is that the listbox treats each expander as an item (obviously) and allows selection and highlighting. Highlighting is a little ugly and could be disabled, but the selection causes me some issues because it causes the list to scroll to show as much of the expanded expander as possible.
Is there a WPF control that is a little like a stackpanel (perhaps) that would allow me to bind the contained controls using item templating but without the selection and highlighting?
<ListBox Grid.Row="0" Grid.Column="0" Width="Auto" SelectionMode="Single" ItemsSource="{Binding Path=MeasurementSources}">
<ListBox.ItemTemplate>
<DataTemplate>
<Expander Header="{Binding Name}" IsEnabled="{Binding Available}">
<ListBox Width="Auto" SelectionMode="Single"
ItemsSource="{Binding Path=Measurements}"
SelectedItem="{Binding Path=SelectedMeasurement}">
<ListBox.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text=" "/>
<TextBlock Text="{Binding Created}"/>
</WrapPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Expander>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If you want List-like capabilities without selection capabilities, you should use an ItemsControl - incidentally the base class of Selector which in turn is the base class of ListBox
The whole thing then just becomes
<ItemsControl Width="Auto" ItemsSource="{Binding Measurements}"
<ItemsControl.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<TextBlock Text=" "/>
<TextBlock Text="{Binding Created}"/>
</WrapPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Obviously, you cannot bind a selected item in this case.
This is a useful piece of information that I had not realised.
http://msdn.microsoft.com/library/windows/apps/hh780657.aspx
Note ItemsControl is the base class for several common collection
controls, including ListView, GridView, FlipView, ListBox, and
ComboBox controls. These examples use the ListView and GridView
controls, but the info applies generally to ItemsControls.
In other words using the ItemsControl really is the way to solve my issue because using a ListBox and then trying to disable the highlight and the selection functionality really is turning it back into it's own base class.
The best solution is for me:
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<!-- With focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}"
Color="Transparent" />
<!-- Without focus -->
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}"
Color="Transparent" />
<!-- Text foreground -->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}"
Color="Black" />
</Style.Resources>
<Setter Property="FocusVisualStyle" Value="{x:Null}"></Setter>
</Style>
and I found it few months ago somwhere on stackoverflow :)
I have a simple ListView bound to a collection of Calculations. The view calls the calc Name property in the display. I have set the contextmenu to the individual items in the listview but on right click the context menu shows up as a tiny box with nothing in. What am i missing?
<ListView x:Name="CalcList" ItemsSource="{Binding Calculations}">
<ListView.ItemTemplate>
<DataTemplate DataType="x:Type lib:Calculation">
<DataTemplate.Resources>
<ContextMenu x:Key="CalcMenu">
<MenuItem Header="Delete Calculation" Click="MenuItem_Click"/>
<MenuItem Header="Another"/>
<MenuItem Header="Another"/>
</ContextMenu>
</DataTemplate.Resources>
<Border BorderBrush="Black" BorderThickness="1" Margin="2">
<Border.ContextMenu>
<ContextMenu ContextMenu="{StaticResource CalcMenu}"/>
</Border.ContextMenu>
<TextBlock MouseLeftButtonDown="DisplayCalc" Text="{Binding Path=Name}"></TextBlock>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Thanks.
If anything, you have a syntax error the way you define the Border.ContextMenu element. The correct syntax (of the Border Element):
<Border BorderBrush="Black" BorderThickness="1"
Margin="2"
ContextMenu="{StaticResource CalcMenu}">
<TextBlock ... />
</Border>
Saying that, there is a lot of optimization you can do. First, instead of instantiating a context menu for each item, you can move the CalcMenu to the section (one level up), or even farther up - to the main window.
Second, why do you define a separate context menu for each item? Is it really important context menu won't popu when mouse is in the margin between items? simply set the context menu to the entire list:
<ListView x:Name="CalcList" ContextMenu="{StaticResource CalcMenu}">
...
and define the CalcMenu as a main window resources, or inline the ListView element (not a static resource).
I've been templating ListBoxes for sometime in WPF, but I was wondering if there was a way to have a template for the ListBoxItem that would apply to all the items in the ListBox, but also have a ItemTemplateSelector to alter the contents of the containers.
I have a list of strings and images and I want to display them uniquely such that the image displays with a frame and strings display in a textbox to be edited. I made an ItemTemplateSelector and select the template based on the type. However I want to add some controls, like a button to delete and a checkbox to display selection to both templates.
I know I can add both objects to both templates for strings or images, but I want it to be able to scale and not have to added each time I add a template. Any thoughts?
You could use the ItemContainerStyle to override the Template of the ListBoxItems (probably not something i would do).
Alternatively you can define a ItemTemplate which frames your Templates by using a ContentControl, e.g.
<ListBox ItemsSource="{Binding Data}">
<ListBox.Resources>
<!-- The frame that is applied to all items -->
<ControlTemplate x:Key="commonFrameTemplate" TargetType="{x:Type ContentControl}">
<Border BorderBrush="Red" BorderThickness="2" CornerRadius="5" Padding="5">
<StackPanel>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"/>
<ContentPresenter /> <!-- Where the individual templates end up -->
<Button Content="Delete"/>
</StackPanel>
</Border>
</ControlTemplate>
<!-- Define templates without using a x:Key but setting the DataType,
the template will automatically be applied, no need for a
template-selector -->
<DataTemplate DataType="{x:Type local:Employee}">
<TextBlock Text="{Binding Name}" Foreground="Red"/>
</DataTemplate>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<!-- By setting the content to {Binding} the templating is delegated
in a way, if you must use a selector, define one here as
ContentTemplateSelector -->
<ContentControl Template="{StaticResource commonFrameTemplate}"
Content="{Binding}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I have done every thing I can think of, but the textbox just does not display the values.
Where is my mistake?
<dxg:GridColumn FieldName="secUserName" Header="TRAIL">
<dxg:GridColumn.DisplayTemplate>
<ControlTemplate>
<StackPanel>
<TextBox Text="{Binding Path=Data.secUserName, Mode=TwoWay}" ></TextBox>
</StackPanel>
</ControlTemplate>
</dxg:GridColumn.DisplayTemplate>
and in vb
'<!-- load the datagrid -->
Module1._Context.Load(Module1._Context.GetGESECsQuery())
GridControl1.AutoPopulateColumns = False
GridControl1.DataSource = Module1._Context.GESECs
I suggest that you use our TextEdit instead of the standard TextBox:
<dxg:GridColumn.DisplayTemplate>
<ControlTemplate>
<StackPanel>
<TextEdit EditValue="{Binding Path=DataContext.secUserName}"></TextEdit>
</StackPanel>
</ControlTemplate>
</dxg:GridColumn.DisplayTemplate>
If this does not help, please remove the template and make certain that the grid has a column bound to the secUserName field and it shows data in runtime.