Is there any way to customize telerik radmenuitem header in wpf? - wpf

I'm trying to customize a header in radmenuitem to have header and infoicon in leftside of header, but I couldn't achieve it because text binding is not working.
Also I have an icon at left which is like
consider this for ref which I want --- "icon header infoicon"
I tried this code
<telerik:RadMenuItem
Command="{Binding }"
CommandParameter="{Binding}"
<telerik:RadMenuItem.IconTemplate>
<DataTemplate>
<image/>
</DataTemplate>
</telerik:RadMenuItem.IconTemplate>
<telerik:RadMenuItem.HeaderTemplate>
<DataTemplate>
<stackpanel>
<textblock text="{binding RelativeSource={RelativeSource AncestorType={x:Type UserControl} ,path=datacontext.text ,updatsourcetrigger=propertychanged,mode=twoway/>
<image/
</DataTemplate>
</stackpanel
</telerik:RadMenuItem.HeaderTemplate>
<telerik:RadMenuItem.Style>
<Style TargetType="{x:Type telerik:RadMenuItem}"/>
</<telerik:RadMenuItem.Style>
</telerik:RadMenuItem>`
expected to happen
(icon header infoicon)
I'm getting like this
(icon infoicon) header is missing

Related

TextBlock inside MenuItem does not became gray if MenuItem is Disabled

If I use this code:
<MenuItem x:Name="MenuSave" Header="Save" IsEnabled="False"/>
when MenuSave is disabled (in real code by a RoutedUICommand programmatically), the Header is disabled and text is gray.
But if I need more text like here:
<MenuItem x:Name="MenuSaveAs" IsEnabled="False">
<MenuItem.Header >
<StackPanel Orientation="Horizontal">
<TextBlock Text="Save as"/>
<TextBlock> ...</TextBlock>
</StackPanel>
</MenuItem.Header>
</MenuItem>
In this case, the Header is disabled but text is not gray.
How can I obtain text gray with composite text?
This is just simplified code to explain the problem, the real code is combination of translated terms.
If you add the TextBlock thorough a HeaderTemplate, the color will be applied for the disabled state. By the way, you can use multiple Runs instead, so the same TextBlock is populated. If you bind a data item as Header, you can bind its properties in the template to the Runs.
<MenuItem x:Name="MenuSaveAs" IsEnabled="False">
<MenuItem.HeaderTemplate>
<DataTemplate>
<TextBlock>
<Run Text="Save as"/>
<Run> ...</Run>
</TextBlock>
</DataTemplate>
</MenuItem.HeaderTemplate>
</MenuItem>
Alternatively, if you need to format a string with a bound property, use HeaderStringFormat.
<MenuItem x:Name="MenuSaveAs"
IsEnabled="False"
Header="{Binding NameOfTheSavedItem}"
HeaderStringFormat="Save as {0}...">
If you really insist on setting the header directly, a workaround would be to bind the Foreground of TextBlock explicitly to the TextElement.Foreground of the ContentPresenter in the MenuItem control template. You can bind it on each TextBlock or add an implicit style that applies to all TextBlocks in scope automatically. Please note the word all.
<Menu>
<Menu.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Foreground" Value="{Binding (TextElement.Foreground), RelativeSource={RelativeSource AncestorType=ContentPresenter}}"/>
</Style>
</Menu.Resources>
<MenuItem x:Name="MenuSaveAs"
IsEnabled="True">
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Padding="0" Text="Save as"/>
<TextBlock Padding="0" Text="..."/>
</StackPanel>
</MenuItem.Header>
</MenuItem>
</Menu>
Please be aware that I suggest to use a single TextBlock with Runs for sentences or paragraphs in general, because panels with multiple TextBlocks result in incorrect spacing and alignment that do not match the typesetting that TextBlock and other document related types provide. It usually looks odd and disjointed and does not take into account the characteristics of a font.
I found an other easy way using <Label Padding="0"..>, instead af <TextBlock ..>:
<MenuItem x:Name="MenuSaveAs" IsEnabled="False">
<MenuItem.Header >
<StackPanel Orientation="Horizontal">
<Label Padding="0" Content="Save as"/>
<Label Padding="0" Content="..."/>
</StackPanel>
</MenuItem.Header>

DataGrid column header text wrapping in silverlight

I am using a DataGrid in my silverlight project and I want one column to wrap it's header text. I know using a style for the header might be the answer but I want to know if there is a wrap property for a datagrid column header?
Here is my code:
<data:DataGrid x:Name="gridViewResources"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding OpportunityResourceDetailList, Mode=TwoWay}" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header="#" Width="Auto">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PositionLevel.FullPositionAndLevelName}" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
Thanks!
I haven't found a way to get Silverlight to automatically wrap the header (in much the same way as the TextWrapping property of a TextBlock does). I suspect that it's not possible due to a limitation of the DataGridColumn.Header property:
Use discretion when using objects as header content; not all Silverlight objects are suitable for use within the limited presentation surface that appears for headers.
However, you can 'manually' wrap header text. If you put a newline in the header text, the header text will be broken over two lines at that point. (In XAML, you use the character entity
.) For example, the following header text appears split over three lines:
<sdk:DataGridTextColumn Header="ABCD
EFGH
IJKL" />
There is no specific property on a DataGridColumn to support this but once you have created the right style it is just as easy - simply set the HeaderStyle property for the specific column.
Create a Style resource with a TargetType of DataGridColumnHeader and set the ContentTemplate property to be a DataTemplate containing a TextBlock with the TextWrapping property set to Wrap. I've enclosed the TextBlock within a Grid panel to keep this closer to the default DataTemplate used by the ContentPresenter. Apply this style to a specific column using the HeaderStyle property or to the whole DataGrid using the ColumnHeaderStyle property.
Note that you will need to constrain the width of the Column to something less than the header text for the wrapping to take affect unless you specifically restrict the width of the TextBlock in the DataTemplate.
<Style x:Key="CustomDataGridColumnHeaderStyle" TargetType="sdk:DataGridColumnHeader" BasedOn="{StaticResource DefaultDataGridColumnHeaderStyle}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding}" TextWrapping="Wrap" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
...
<sdk:DataGrid >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Header Name" Binding="{Binding Xxx}" Width="80" HeaderStyle="{StaticResource CustomDataGridColumnHeaderStyle}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
here is my code
<DataGrid.ColumnHeaderStyle>
<Style TargetType="ContentControl">
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
<Setter Property="ContentTemplate" >
<Setter.Value >
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="Wrap" FontWeight="Bold" TextAlignment="Center" LineHeight="20"></TextBlock></DataTemplate>
</Setter.Value>
</Setter>
</Style>
`enter code here`</DataGrid.ColumnHeaderStyle>

WPF + Binding Command and Header of a Context Menu Item using MVVM

I created a WPF application and am following MVVM Pattern. I have a context menu in my xaml and I need to bind the command and Header text. Using the following code I can bind the Header of the context menu with the "MenuItemName" which is a property in BOList which is an observable collection. My issue is that command is not getting fired? I changes the Item source of the Context Menu to datacontext
(DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}")
Command is working fine but my header is getting blank. Is there a way to bind my header and command of a menu item? Here the command MenuClick is a Icommand property in the VM and MenuItemName is a property inside BOList which is an observable collection binded to my ListBox.
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="btnClickMe" Command="{Binding ButtonCommand}" Content="Click Me" />
<ListBox ItemsSource="{Binding BOList}" x:Name="lstDemo" SelectedItem="{Binding BussinessObj,Mode=OneWayToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="stkStyleRender" Orientation="Horizontal" Background="Cyan" Width="525" Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" >
<TextBlock x:Name="txtId" Text="{Binding FirstName}"></TextBlock>
<TextBlock x:Name="txtName" Text="{Binding LastName}"></TextBlock>
<StackPanel.ContextMenu>
<ContextMenu x:Name="cntMnuTest" ItemsSource ="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" >
<MenuItem Header="{Binding MenuItemName}" Command="{Binding MenuClick}" CommandParameter="Icon"></MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
Hi Identified the issue.
If we set Item Source of the context menu to BOList (observable collection ) command wont get fired because the ICommand definition is in Window data context (vm).
We need to handle the code like wise.
Since debugging is not possible for binding , I was beating around the bush :-)
This link helped me a lot WPF Tutorial - Debug Databinding Issues in WPF
In context menu use DataContext instead of using Items source
then bind your menu item
try this:
<MenuItem Header="{Binding Path=PlacementTarget.MenuItemName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}" Command="{Binding Path=PlacementTarget.MenuClick, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}" />

Display image in combobox column in datagrid

I'd like to have a combobox in a datagrid to show a list of actual images, instead of text.
I can make this work by manually building a combobox, but cant seem to do this via binding (which is about the only way the datagrid can be used).
I also tried a template column, but got the same results- listing of text showing the name of the image class. Any samples demonstrating this?
Nest as many templates as you need, if your ComboBox shows the class name just set ComboBox.ItemTemplate to do something with your class. Here i assume that MyImageList consists of ImageSource objects (needs some more sizing specifications):
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding MyImageList}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Alternatively you could porbably use a DataGridComboBoxColumn as well, just use the CellStyle to set up a DataTemplate which can display your images:
<DataGridComboBoxColumn ItemsSource="{Binding MyImageList}">
<DataGridComboBoxColumn.CellStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridComboBoxColumn.CellStyle>
</DataGridComboBoxColumn>

Force TextBlock to wrap in WPF ListBox

I have a WPF listbox which displays messages. It contains an avatar on the left side and the username and message stacked vertically to the right of the avatar. The layout is fine until the message text should word wrap, but instead I get a horizontal scroll bar on the listbox.
I've Googled and found solutions to similar issues, but none of them worked.
<ListBox HorizontalContentAlignment="Stretch" ItemsSource="{Binding Path=FriendsTimeline}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border BorderBrush="DarkBlue" BorderThickness="3" CornerRadius="2" Margin="3" >
<Image Height="32" Width="32" Source="{Binding Path=User.ProfileImageUrl}"/>
</Border>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=User.UserName}"/>
<TextBlock Text="{Binding Path=Text}" TextWrapping="WrapWithOverflow"/> <!-- This is the textblock I'm having issues with. -->
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Contents of the TextBlock can be wrapped using property TextWrapping.
Instead of StackPanel, use DockPanel/Grid.
One more thing - set ScrollViewer.HorizontalScrollBarVisibility property to Disabled value for the ListBox.
Updated Hidden to Disabled based on comment from Matt. Thanks Matt.
The problem might not be located in the ListBox. The TextBlock won't wrap, if one of the parent controls provides enough space, so that it hasn't the need to wrap. This might be caused by a ScrollViewer control.
If you want to prevent TextBlock to grow, and you want it to just fit in the size of the listbox, you should set the width of it explicitly.
In order to change it dynamically, it means not a fix value, but you need to bind it to its proper parent element in the visual tree. You can have something like this:
<ListBox ItemsSource="{Binding MyItems}" Name="MyListBox">
<ListBox.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="Width"
Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ScrollContentPresenter}, Path=ActualWidth}" />
</Style>
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
If it does not work, try to find the proper elements (which has to be binded to what) with the Live Visual Tree in Visual Studio.

Resources