I have the following XAML
<MenuItem Header="_Recent Studies"
Height="22"
ItemsSource="{Binding RecentFiles}">
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="Header" Value="{Binding FullFileName}"/>
</Style>
</MenuItem.Resources>
</MenuItem>
Which displayed my recent files like
However, I want to display the item number of the MenuItem next to the file name like VS2012 does.
FileNameA.f
FileNameB.x
FileNameC.j
etc. To do this I decided to use a converter Where if I were just getting the number without the file name I could do this. But I want to incorporate this with multi-binding so I can write something like
<MultiBinding StringFormat="{}{0}. {1}">
<Binding Path="??"/>
<Binding Path="FullFileName"/>
</MultiBinding>
I don't know what to write in the above. How can I prefix my files names with the number that the file is in the list without adding an index property to my FullFileNames which would make things more complex?
Thanks for your time.
Edit. This is how I use the below answer in my code
<MenuItem Header="_FILE">
...
<MenuItem Header="_Recent Studies"
ItemsSource="{Binding RecentFiles}"
AlternationCount="{Binding RecentFiles.Count}"
HeaderTemplate="{x:Null}">
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}"
BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}. {1}">
<Binding Path="(ItemsControl.AlternationIndex)"
RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}"
Converter="{StaticResource IntPlusNConverter}"/>
<Binding Path="FullFileName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</MenuItem.Resources>
</MenuItem>
<Separator/>
<MenuItem Header="E_xit"
Height="22"
Icon="{Binding Source={StaticResource Close},
Converter={StaticResource drawingBrushToImageConverter}}"
Command="{Binding ExitCommand}" />
</MenuItem>
This works! However, all my XAML for the FILE MenuItem block is being highlighted and I get a compile-time error (the code runs and works though!), saying
An object of the type "System.Windows.StaticResourceExtension" cannot be applied to a property that expects the type "System.Windows.Style".
Why is this happening and how can I resolve it?
Thanks for your time.
RESULT!
You should be able to do it with AlternationIndex like in this answer
Finding Listbox Index of ListBoxItem (ItemsTemplate to specify Visual COntent)
You may have to override the HeaderTemplate because the StringFormat may not work correctly because Header is an object not a string
Example:
<MenuItem Header="_Recent Studies" ItemsSource="{Binding RecentFiles}" AlternationCount="{Binding RecentFiles.Count}" HeaderTemplate="{x:Null}">
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource {x:Type MenuItem}}">
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}. {1}">
<Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type MenuItem}}" />
<Binding Path="FullFileName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</MenuItem.Resources>
</MenuItem>
Result:
Related
I have a ListBox that shows search results, grouped by their type, implemented like this:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<TextBlock Margin="10 5 0 0">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}: {1}">
<Binding Path="Name" />
<Binding Path="ItemCount" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Expander.Header>
<Expander.Content>
<ItemsPresenter />
</Expander.Content>
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
This is working fine.
Now I want to collapse the Expander if there are 10 or more items in a group (only after count changes, keeping the possibility for the user to expand and collapse manually). How can I achieve this?
I wrote an IsLessThanConverter : IValueConverter that takes a parameter and returns true if the passed value is less than the parameter.
However, I don't know how to integrate this converter here. I tried something like this, but the converter is never called:
<Expander IsExpanded="{Binding Path=Count,
RelativeSource={RelativeSource Self},
Converter={StaticResource IsLessThanConverter},
ConverterParameter=10,
Mode=OneWay}">
...
In MVVM pattern without Prism Library with WPF , view model is injected in manually. DataTrigger Path can be specified by
Path=DataContext.ColumnColorSlideStatus}". It works fine.
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListView}}, **Path=DataContext.ColumnColorSlideStatus}"**
Value="Review">
<Setter Property="Background">
<Setter.Value>
<Binding
Converter="{StaticResource ColumnBackGroundColorConverter}"
ConverterParameter="Review"
RelativeSource="{RelativeSource Self}" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListView}}, **Path=DataContext.ColumnColorSlideStatus}"**
Value="NFR">
<Setter Property="Background">
<Setter.Value>
<Binding
Converter="{StaticResource ColumnBackGroundColorConverter}"
ConverterParameter="NFR"
RelativeSource="{RelativeSource Self}" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
When Using Prism Library with WPF, the view and viewmodel is linked automatically by code below.
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
There is no instance of DataContext in View Xaml Code. the DataTrigger Path can not be specified to the DataContext.ColumnColorSlideStatus. DataTrigger can not be triggered.
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListView}}, **Path=ColumnColorSlideStatus}"**
Value="Review">
<Setter Property="Background">
<Setter.Value>
<Binding
Converter="{StaticResource ColumnBackGroundColorConverter}"
ConverterParameter="Review"
RelativeSource="{RelativeSource Self}" />
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListView}}, **Path=ColumnColorSlideStatus}"**
Value="NFR">
<Setter Property="Background">
<Setter.Value>
<Binding
Converter="{StaticResource ColumnBackGroundColorConverter}"
ConverterParameter="NFR"
RelativeSource="{RelativeSource Self}" />
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
```
Is any suggestions to get instance of viewmodel into view when Prism Library is used or some way works around it
I have created a ContextMenu with a Menu inside it. The Menu doesn't always have items. When there are no items I want to hide the ContextMenu.
Relevant code in my style (generic.xaml)
<Grid.ContextMenu>
<ContextMenu Margin="10,10,0,13" Name="ContextMenu" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False">
<Menu>
<Menu.ItemsSource>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ChildCommands"/>
</Menu.ItemsSource>
<Menu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="MenuItem.Header" Value="{Binding Command.Text}"/>
<Setter Property="MenuItem.IsEnabled" Value="False"/>
</Style>
</Menu.ItemContainerStyle>
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</Menu.ItemsPanel>
</Menu>
</ContextMenu>
</Grid.ContextMenu>
How can I hide the ContextMenu when there are no menuitems inside it?
EDIT : I fixed it by changing the Menu tags to ContextMenu tags.
Use the visibility property by the context menu. Too hide the context menu bind the menuitemscount and use a converter to convert the Count to the visibility enum.
I changed the Menu tags to ContextMenu tags and it works now. The ContextMenu is only visible when there are items in it.
Code:
<Grid.ContextMenu>
<ContextMenu Margin="10,10,0,13" Name="ContextMenu" HorizontalAlignment="Left" VerticalAlignment="Top" IsOpen="False">
<ContextMenu.ItemsSource>
<Binding RelativeSource="{RelativeSource TemplatedParent}" Path="ChildCommands"/>
</ContextMenu.ItemsSource>
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="MenuItem.Header" Value="{Binding Command.Text}"/>
<Setter Property="MenuItem.IsEnabled" Value="False"/>
</Style>
</ContextMenu.ItemContainerStyle>
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
</ContextMenu>
</Grid.ContextMenu>
I'm having a DataGridColumnHeader Sytle, in that I'm having a Button for Filtering. I need to Pass the Button HashCode as a Command Parameter
<Style TargetType="{x:Type DataGridColumnHeader}" x:Key="DummyFilterDataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Button Command="{Binding Path=DataContext.FilterPopUpCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValueConverterKey}">
<Binding RelativeSource="{ RelativeSource Mode=FindAncestor,
AncestorType={x:Type cust:DataGrid}}" />
<Binding Path="Column"
RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding Path="HashCode" />
</MultiBinding>
</Button.CommandParameter>
</Button>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Note: My Requirement is to pass HashCode only from the XAML not in the
C# extraction from a Button Control.
Since the only way to get the HashCode of the Button is through the GetHashCode() method, i suggest you to pass a reference of the Button itself to the Command like this :
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Button x:Name="Btn" Command="{Binding Path=DataContext.FilterPopUpCommand,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type Window}}}">
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource MultiValueConverterKey}">
<Binding RelativeSource="{ RelativeSource Mode=FindAncestor,
AncestorType={x:Type cust:DataGrid}}" />
<Binding Path="Column"
RelativeSource="{RelativeSource Mode=TemplatedParent}" />
<Binding ElementName="Btn" />
</MultiBinding>
</Button.CommandParameter>
</Button>
</ControlTemplate>
In the MultivalueConverter, extract the Hash code and pass it to the Command :
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values==null)
return null;
var hashCode = (values[2] as Button).GetHashCode();
//the rest of your code
}
I have a WPF application which contains a Datagrid consisting of a column of buttons. The respective XAML code is as follows.
<DataGridTemplateColumn Header="Closed" Width="60">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button>
<Button.Content>
<Image>
<Image.Source>
<MultiBinding Converter="{StaticResource ImageConverter}"
ConverterParameter="Closed">
<Binding Path="IsClosed"/>
<Binding Path="DataContext.TickImage" RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}"/>
<Binding Path="DataContext.CrossImage" RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}"/>
</MultiBinding>
</Image.Source>
</Image>
</Button.Content>
<Button.Command>
<Binding Path="DataContext.ClosedClicked" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}"/>
</Button.Command>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The TickImage and CrossImage are image sources either of which is selected based on the value of IsClosed .
Now in the ViewModel I need to write a code to toggle images(b/w TickImage and CrossImage ) when the button is clicked. In other words, I need a way to simultaneously bind the Button with an ICommand and a BitmapImage variable.
Please help!!
if your IsClosed is just a toggle to know if button was pressed or release then you can achieve this by just using triggers like below:
<ToggleButton>
<ToggleButton.Content>
<Image>
<Image.Style>
<Style TargerType="Image">
<Setter Property="Source" Value="{Binding Path="DataContext.TickImage" RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource="{RelativeSource AncestorType={x:Type ToggleButton}}" Value="true">
<Setter Property="Source" Value="{Binding Path="DataContext.CrossImage" RelativeSource="{RelativeSource AncestorType={x:Type UserControl}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ToggleButton.Content>
</ToggleButton>