xceed IntegerUpDown: shifted context menu values - c#

I use Xceeed Wpf Toolkit and IntegerUpDown:
xmlns:XceedToolkit="clr-namespace:Xceed.Wpf.Toolkit;assembly=Xceed.Wpf.Toolkit"
<XceedToolkit:IntegerUpDown Grid.Column="1" Value="{Binding SelectedYear}" HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
But, when i do right click on this control, take this:
If i make right click on anohter control like TextBox it is look normal.
Can you help me to fix it?

According to WPF Textbox's TextAlignment changes its default context menu item's alignment as well, you have to rebuild the context menu, since the default can't be changed.
<XceedToolkit:IntegerUpDown>
<XceedToolkit:IntegerUpDown.ContextMenu>
<ContextMenu TextBlock.TextAlignment="Left">
<MenuItem Command="ApplicationCommands.Copy" />
<MenuItem Command="ApplicationCommands.Cut" />
<MenuItem Command="ApplicationCommands.Paste" />
</ContextMenu>
</XceedToolkit:IntegerUpDown.ContextMenu>
</XceedToolkit:IntegerUpDown>
The issue is not specific to XceedToolkit:IntegerUpDown but applies to many controls with default context menu and TextAlignment property.
If you rather want to hack around with styles instead of replacing the context menu, your best bet for a target might be the Popup, since the context menu elements are internal classes somewhere, so creating a style for them won't work out of the box.
<XceedToolkit:IntegerUpDown>
<xt:IntegerUpDown.Resources>
<Style TargetType="Popup">
<Setter Property="TextBlock.TextAlignment" Value="Left"/>
</Style>
</xt:IntegerUpDown.Resources>
</xt:IntegerUpDown>

Related

WPF - Focus Control Within DataTemplate applied to FlyoutControl

I have a DataTemplate which contains a TextBox. The DataTemplate is bound to the ContentTemplate property of a Style for the DevExpress FlyoutControl. The Flyout Control itself is within the ControlTemplate of another TextBox.
When the TextBox with the FlyoutControl is focused, I want to redirect focus to the first TextBox in the FlyoutControl's ContentTemplate (from the DataTemplate). Setting FocusManager.FocusedElement={Binding RelativeSource={RelativeSource Self}} on the TextBox I want focused accomplishes this the first time, but once the Flyout has loaded it no longer works.
I have tried every suggestion I can find and nothing so far has worked. I can get the TextBox I want to reference in code and call Focus(), but it always returns false. At best, when I try to focus it in code, the Flyout is focused instead, but never the TextBox within the Flyout.
Here is what each relevant part looks like (irrelevant code omitted):
<DataTemplate x:Key="FlyoutTemplate">
<Grid>
<dxe:TextEdit x:Name="TextThatWantsFocus"
FocusManager.FocusedElement={Binding RelativeSource={RelativeSource Self}}" />
</Grid>
</DataTemplate>
...
<Style x:Key="FlyoutStyle" TargetType="dxe:FlyoutControl">
<Setter Property="ContentTemplate" Value="{StaticResource FlyoutTemplate}"/>
</Style>
...
<dxe:TextEdit>
<dxe:TextEdit.Template>
<ControlTemplate>
<StackPanel>
<dxe:TextEdit x:Name="InnerTextEdit" />
<dxe:FlyoutControl Style="{StaticResource FlyoutStyle}"/>
</StackPanel>
</ControlTemplate>
</dxe:TextEdit.Template>
</dxe:TextEdit>
The flyout is being opened in code. It is here that I also would like to focus the TextBox (TextThatWantsFocus). However, nothing I have tried will give it focus (except for FocusManager handling it the first time), including the typical SO answer involving triggers. Any ideas would be greatly appreciated.
I took DmitryG's advice and submitted a DevExpress support ticket, and they were able to provide a solution.
The issue was resolved by handling the Loaded event of the TextEdit I want focused and using the dispatcher to focus it:
private void TextThatWantsFocus_Loaded(object obj, RoutedEventArgs e)
{
var text = obj as FrameworkElement;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(delegate()
{ text.Focus(); }));
}
I suggest you using the FocusBehavior from DevExpress MVVM Framework:
<DataTemplate x:Key="FlyoutTemplate">
<Grid>
<dxe:TextEdit>
<dxmvvm:Interaction.Behaviors>
<local:FocusBehavior/>
</dxmvvm:Interaction.Behaviors>
</dxe:TextEdit>
</Grid>
</DataTemplate>

Template for basic reusable button

In WPF (VS2013), I'm creating a button like so:
<Button>
<Label>1</Label>
</Button>
Each of these buttons will have more to it, such as increased font size of the Label, grid row/column assignment, and I might use a binding for the label so that I can change the number. I'm creating a calculator app so I need to reuse this button 10 times (one for each number 0-9). Instead of copying/pasting this button XML 10 times, I wanted to see if I could templatize it.
I've read a little about ControlTemplate and DataTemplate, but I'm not sure if either of these are the correct thing to use. It's also not clear to me what should be a style or what should be a template.
So if someone could help me understand how to "templatize" the button and its styles (e.g. width, height, font size, etc) so that they can be easily reused, that would help a ton. Guidance is appreciated!
Use a ControlTemplate when you want to overwrite the entire template for a control, use a DataTemplate when you want to tell WPF how to draw a data object (usually the DataContext), and use ContentTemplate when you want to tell WPF how to draw the Content property of an object.
Creating a whole new ControlTemplate is quite complex. To demonstrate, check out this MSDN example for an example ControlTemplate for a Button.
In your case, I would recommend creating a Style for your button with setters for common properties such as Height, Width, Font, etc. If you want to draw your button's Content property in a custom way without completely overwriting the button template, include a ContentTemplate style setter to tell WPF how to draw the Button.Content property.
<Button Style="{StaticResource CalculatorButton}" Content="1" />
and
<Style x:Key="CalculatorButton" TargetType="{x:Type Button}">
<Setter Property="Height" Value="50"/>
<Setter Property="Width" Value="50"/>
<Setter Property="FontSize" Value="14" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding }" FontFamily="Wingdings 3" FontWeight="Bold" FontSize="18" Foreground="Navy" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
The ControlTemplate defines how the button looks, the ContentTemplate defines how the Button.Content looks, and the DataTemplate used for the ContentTemplate is defining how the data object of "1" will be drawn.
You can start with a copy of the style of the button. Use Blend (part of VS) to create that: open the context menu of the button inside the object tree, then select "Edit template" (or similar, don't have an english version at hand), then "Copy of template" (or alike).
Now you may change properties (in designer or XAML). Every button that shall have this style needs to reference this new ressource.
You need to create a new Style of a button. Learning curve is not too steep, but the benefits are enormous. You can start learning about it here: http://msdn.microsoft.com/en-us/library/ms745683(v=vs.110).aspx
Long story short: Open your project with Blend, right-click on your button, "Edit Style", "Edit a copy". If you choose to define it in Application, you can reuse it among other pages (it will be then in you App.xaml file)
Once you have the base style, edit it as much as you need.

Context Menu Style not applied until right click

I have a context menu attached to a button on a toolbar on one of my controls in WPF (.NET 4.0). The context menu has a style assigned to it in the XAML that defines the context menu. Left clicking on the button opens the button's context menu if it isn't opened already.
Here's the relevant XAML:
<Button x:Name="fileButton" Foreground="White" Margin="7, 0, -3, 0" VerticalAlignment="Stretch" MaxHeight="70" MaxWidth="78" MinHeight="55" MinWidth="62" Style="{DynamicResource ImageButton}" utils:WpfImageUtil.Image="{StaticResource fileButton}" Template="{DynamicResource GlassButton}" Content="File" Visibility="Visible" Click="fileButton_Click">
<Button.ContextMenu>
<ContextMenu Style="{DynamicResource ContextMenuStyle}">
<MenuItem x:Name="saveMenuItem" Header="Save" Click="saveMenuItem_Click" Style="{DynamicResource MenuItemStyle}" />
<MenuItem x:Name="saveDrawingMenuItem" Header="Save Drawing" Click="saveMenuItem_Click" Style="{DynamicResource MenuItemStyle}" />
<MenuItem x:Name="openMenuItem" Header="Open" Style="{DynamicResource MenuItemStyle}">
<MenuItem x:Name="openFromFile" Header="From File" Style="{DynamicResource MenuItemStyle}" />
<MenuItem x:Name="openFromDesktop" Header="From Desktop" Style="{DynamicResource MenuItemStyle}" />
</MenuItem>
<MenuItem x:Name="iconsMenuItem" Header="Icons" ItemsSource="{Binding}" Style="{DynamicResource MenuItemStyle}"/>
<MenuItem x:Name="prefsMenuItem" Header="Preferences" Style="{DynamicResource MenuItemStyle}"/>
</ContextMenu>
</Button.ContextMenu>
</Button>
ContextMenuStyle is defined in a resource dictionary that is properly referenced.
When the context menu is opened with a left click, the style I have defined isn't applied to the menu, as shown below:
However, if the user right-clicks and opens the context menu the traditional way, the style is applied as expected:
Afterwards, left-clicking the button will show the style correctly:
I have been trying to figure this out for some time, but haven't been able to come up with any reason that this issue occurs. It seems like some kind of bug to me, but I'm not entirely sure. I also don't know what happens at the lower level when controls are right-clicked on that would cause the style to get applied correctly.
You should assign ContextMenu Style property in code (FindResource method msdn):
private void fileButton_Click(object sender, RoutedEventArgs e)
{
if (fileButton.ContextMenu.Style == null)
fileButton.ContextMenu.Style = this.FindResource("ContextMenuStyle") as Style;
fileButton.ContextMenu.IsOpen = true;
}
ContextMenu Overview (http://msdn.microsoft.com/en-US/library/ms742558.aspx)
A ContextMenu is attached to a specific control. The ContextMenu
element enables you to present users with a list of items that specify
commands or options that are associated with a particular control, for
example, a Button. Users right-click the control to make the menu
appear. ...
When you right-click on the control, style will be applied to the ContextMenu. So if you want to open ContextMenu in code, you should check if style is equal null and if it's true, you should assign appropriate style.

avalondock override contextmenu - cannot find the type ContextMenuElement

This is a follow up question to User control in avalon dock and separate window - I've got the window opening nicely which I thought would be the hard part; but i'm having difficulty in changing the contextmenu.
I'm new to WPF and avalondock and it's probably something simple but i'm missing it.
Previous question pointed me to http://avalondock.codeplex.com/SourceControl/changeset/view/96370#1749982 as an example. I was getting a "ContextMenuElement not found" error so went for something simpler:
http://avalondock.codeplex.com/discussions/246250 - this is about replacing with French text but I could adapt it. I couldn't get it to work and then tried copy pasting verbatim and still have same error:
Cannot find the type ContextMenuElement. Note that type names are case sensitive
I get this on the resource dictionary and it points to command part of the menu item eg:
<MenuItem Header="Fermer"
Command="avalonDock:DocumentPaneCommands.CloseThis" />
What am I missing ?
Edit: Excerpt of resource dictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:avalonDock="clr-namespace:AvalonDock;assembly=AvalonDock">
<!--Menu contextuel des onglets de l'avalonDock-->
<ContextMenu x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type avalonDock:DockingManager}, ResourceId={x:Static avalonDock:ContextMenuElement.DocumentPane}}">
<MenuItem Header="Fermer"
Command="avalonDock:DocumentPaneCommands.CloseThis" />
<MenuItem Header="Fermer tout sauf cet élément"
Command="{Binding Path=DataContext.FermerCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
<Separator />
The code you are trying to adapt looks like it is for version 1.3 and you might be using the new 2.0 version. The way you change the behaviour of the DockingManager has changed a lot and is now simpler then ever.
This is a small sample to replace the ContextMenu for a Document in the DocumentPane (tested on v2.0.1320):
<ad:DockingManager>
<ad:DockingManager.DocumentContextMenu>
<ContextMenu>
<MenuItem Header="DEMO"/>
</ContextMenu>
</ad:DockingManager.DocumentContextMenu>
</ad:DockingManager>
In the theme you can see how this is done using a style
<Style x:Key="{x:Type avalonDock:DockingManager}" TargetType="{x:Type avalonDock:DockingManager}">
<Setter Property="DocumentContextMenu" Value="{StaticResource AvalonDock_ThemeVS2010_DocumentContextMenu}"/>
...
I would still recommend to just make a copy of the theme project from their website and build your own theme for your application. That way you have all your adaptations neatly stored in a reusable dll.

How are DynamicResources built and their use in contextmenus

Are dynamic resources truly dynamic? If I define a DynamicResource, I realise that an expression is created (where?) that is not translated into a resource until runtime, however, What I do not understans is whether this dynamicresouce, once built, is now "Static"
For instance, if I create a context menu via a dynamicresource, are the menuitems which are created at runtime on access then static, even if they are bound?
If so, how can i create a dynamic context menu in XAML?
This is a very complex subject because there are so many kinds of dynamism within WPF. I will start with a simple example to help you understand some basic concepts you need, then proceed to explain the various ways in which a ContextMenu can be dynamically updated and/or replaced, and how DynamicResource fits into the picture.
Initial example: Dynamically updating ContextMenu referenced through StaticResource
Let's say you have the following:
<Window>
<Window.Resources>
<ContextMenu x:Key="Vegetables">
<MenuItem Header="Broccoli" />
<MenuItem Header="Cucumber" />
<MenuItem Header="Cauliflower" />
</ContextMenu>
</Window.Resources>
<Grid>
<Ellipse ContextMenu="{StaticResource Vegetables}" />
<TextBox ContextMenu="{StaticResource Vegetables}" ... />
...
</Grid>
</Window>
** Note the use of StaticResource for now.
This XAML will:
Construct a ContextMenu object with three MenuItems and add it to Window.Resources
Construct an Ellipse object with a reference to the ContextMenu
Construct a TextBox object with a reference to the ContextMenu
Since both the Ellipse and the TextBox have references to the same ContextMenu, updating the ContextMenu will change the options available on each. For example the following will add "Carrots" to the menu when a button is clicked.
public void Button_Click(object sender, EventArgs e)
{
var menu = (ContextMenu)Resources["Vegetables"];
menu.Items.Add(new MenuItem { Header = "Carrots" });
}
In this sense every ContextMenu is dynamic: Its items can be modified at any time and the changes will immediately take effect. This is true even when the ContextMenu is actually open (dropped down) on the screen.
Dynamic ContextMenu updated through data binding
Another way in which a single ContextMenu object is dynamic is that it responds to data binding. Instead of setting individual MenuItems you can bind to a collection, for example:
<Window.Resources>
<ContextMenu x:Key="Vegetables" ItemsSource="{Binding VegetableList}" />
</Window.Resources>
This assumes VegetableList is declared as an ObservableCollection or some other type that implements the INotifyCollectionChanged interface. Any changes you make to the collection will instantly update the ContextMenu, even if it is open. For example:
public void Button_Click(object sender, EventArgs e)
{
VegetableList.Add("Carrots");
}
Note that this kind of collection update need not be made in code: You can also bind the vegetable list to a ListView, DataGrid, etc so that changes may be made by the end-user. These changes will also show up in your ContextMenu.
Switching ContextMenus using code
You can also replace the ContextMenu of an item with a completely different ContextMenu. For example:
<Window>
<Window.Resources>
<ContextMenu x:Key="Vegetables">
<MenuItem Header="Broccoli" />
<MenuItem Header="Cucumber" />
</ContextMenu>
<ContextMenu x:Key="Fruits">
<MenuItem Header="Apple" />
<MenuItem Header="Banana" />
</ContextMenu>
</Window.Resources>
<Grid>
<Ellipse x:Name="Oval" ContextMenu="{StaticResource Vegetables}" />
...
</Grid>
</Window>
The menu can be replaced in code like this:
public void Button_Click(object sender, EventArgs e)
{
Oval.ContextMenu = (ContextMenu)Resources.Find("Fruits");
}
Note that instead of modifying the existing ContextMenu we are switching to a completely different ContextMenu. In this situation both ContextMenus are built immediately when the window is first constructed, but the Fruits menu is not used until it is switched.
If you want to avoid constructing the Fruits menu until it was necessary you could construct it in the Button_Click handler instead of doing it in XAML:
public void Button_Click(object sender, EventArgs e)
{
Oval.ContextMenu =
new ContextMenu { ItemsSource = new[] { "Apples", "Bananas" } };
}
In this example, every time you click on the button a new ContextMenu will be constructed and assigned to the oval. Any ContextMenu defined in Window.Resources still exists but is unused (unless another control uses it).
Switching ContextMenus using DynamicResource
Using DynamicResource allows you to switch between ContextMenus without explicitly assigning it code. For example:
<Window>
<Window.Resources>
<ContextMenu x:Key="Vegetables">
<MenuItem Header="Broccoli" />
<MenuItem Header="Cucumber" />
</ContextMenu>
</Window.Resources>
<Grid>
<Ellipse ContextMenu="{DynamicResource Vegetables}" />
...
</Grid>
</Window>
Because this XAML uses DynamicResource instead of StaticResource, modifying the dictionary will update the ContextMenu property of the Ellipse. For example:
public void Button_Click(object sender, EventArgs e)
{
Resources["Vegetables"] =
new ContextMenu { ItemsSource = new[] {"Zucchini", "Tomatoes"} };
}
The key concept here is that DynamicResource vs StaticResource only controls when the dictionary is lookup is done. If StaticResource is used in the above example, assigning to Resources["Vegetables"] will not update the Ellipse's ContextMenu property.
On the other hand, if you are updating the ContextMenu itself (by changing its Items collection or via data binding), it does not matter whether you use DynamicResource or StaticResource: In each case any changes you make to the ContextMenu will be immediately visible.
Updating individual ContextMenu ITEMS using data binding
The very best way to update a ContextMenu based on properties of the item that is right-clicked is to use data binding:
<ContextMenu x:Key="SelfUpdatingMenu">
<MenuItem Header="Delete" IsEnabled="{Binding IsDeletable}" />
...
</ContextMenu>
This will cause the "Delete" menu item to be automatically grayed out unless the item has its IsDeletable flag set. No code is necessary (or even desirable) in this case.
If you want to hide the item instead of simply graying it out, set Visibility instead of IsEnabled:
<MenuItem Header="Delete"
Visibility="{Binding IsDeletable, Converter={x:Static BooleanToVisibilityConverter}}" />
If you want to add/remove items from a ContextMenu based on your data, you can bind using a CompositeCollection. The syntax is a bit more complex, but it is still quite straightforward:
<ContextMenu x:Key="MenuWithEmbeddedList">
<ContextMenu.ItemsSource>
<CompositeCollection>
<MenuItem Header="This item is always present" />
<MenuItem Header="So is this one" />
<Separator /> <!-- draw a bar -->
<CollectionContainer Collection="{Binding MyChoicesList}" />
<Separator />
<MenuItem Header="Fixed item at bottom of menu" />
</CompositeCollection>
</ContextMenu.ItemsSource>
</ContextMenu>
Assuming "MyChoicesList" is an ObservableCollection (or any other class that implements INotifyCollectionChanged), items added/removed/updated in this collection will be immediately visible on the ContextMenu.
Updating individual ContextMenu ITEMS without data binding
When at all possible you should control your ContextMenu items using data binding. They work very well, are nearly foolproof, and greatly simplify your code. Only if data binding can't be made to work does it make sense to use code to update your menu items. In this case you can build your ContextMenu by handling the ContextMenu.Opened event and doing updates within this event. For example:
<ContextMenu x:Key="Vegetables" Opened="Vegetables_Opened">
<MenuItem Header="Broccoli" />
<MenuItem Header="Green Peppers" />
</ContextMenu>
With this code:
public void Vegetables_Opened(object sender, RoutedEventArgs e)
{
var menu = (ContextMenu)sender;
var data = (MyDataClass)menu.DataContext
var oldCarrots = (
from item in menu.Items
where (string)item.Header=="Carrots"
select item
).FirstOrDefault();
if(oldCarrots!=null)
menu.Items.Remove(oldCarrots);
if(ComplexCalculationOnDataItem(data) && UnrelatedCondition())
menu.Items.Add(new MenuItem { Header = "Carrots" });
}
Alternatively this code could simply change menu.ItemsSource if you were using data binding.
Switching ContextMenus using Triggers
Another technique commonly used to update ContextMenus is to use a Trigger or DataTrigger to switch between a default context menu and a custom context menu depending on the triggering condition. This can handle situations where you want to use data binding but need to replace the menu as a whole rather than update parts of it.
Here is an illustration of what this looks like:
<ControlTemplate ...>
<ControlTemplate.Resources>
<ContextMenu x:Key="NormalMenu">
...
</ContextMenu>
<ContextMenu x:Key="AlternateMenu">
...
</ContextMenu>
</ControlTemplate.Resources>
...
<ListBox x:Name="MyList" ContextMenu="{StaticResource NormalMenu}">
...
<ControlTemplate.Triggers>
<Trigger Property="IsSpecialSomethingOrOther" Value="True">
<Setter TargetName="MyList" Property="ContextMenu" Value="{StaticResource AlternateMenu}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
In this scenario it is still possible to use data binding to control individual items in both NormalMenu and AlternateMenu.
Releasing ContextMenu resources when the menu is closed
If resources used in a ContextMenu are expensive to keep in RAM you may want to release them. If you are using data binding this is likely to happen automatically, as the DataContext is removed when the menu is closed. If you are using code instead you may have to catch the Closed event on the ContextMenu to deallocate whatever you created in response to the Opened event.
Delayed construction of ContextMenu from XAML
If you have a very complex ContextMenu that you want to code in XAML but don't want to load except when it is needed, two basic techniques are available:
Put it in a separate ResourceDictionary. When necessary, load that ResourceDictionary and add it to MergedDictionaries. As long as you used DynamicResource, the merged value will be picked up.
Put it in a ControlTemplate or DataTemplate. The menu will not actually be instantiated until the template is first used.
However neither of these techniques by itself will cause the loading to happen when the context menu is opened - only when the containing template is instantiated or the dictionary is merged. To accomplish that you must use a ContextMenu with an empty ItemsSource then assign the ItemsSource in the Opened event. However the value of the ItemsSource can be loaded from a ResourceDictionary in a separate file:
<ResourceDictionary ...>
<x:Array x:Key="ComplexContextMenuContents">
<MenuItem Header="Broccoli" />
<MenuItem Header="Green Beans" />
... complex content here ...
</x:Array>
</ResourceDictionary>
with this code in the Opened event:
var dict = (ResourceDictionary)Application.LoadComponent(...);
menu.ItemsSource = dict["ComplexMenuContents"];
and this code in the Closed event:
menu.ItemsSource = null;
Actually if you have only a single x:Array, you may as well skip the ResourceDictionary. If your XAML's outermost element is the x:Array the Opened event code is simply:
menu.ItemsSource = Application.LoadComponent(....)
Summary of critical concepts
DynamicResource is used only for switching values based on which resource dictionaries are loaded and what they contain: When updating the contents of the dictionaries, DynamicResource automatically updates the properties. StaticResource only reads them when the XAML is loaded.
No matter whether DynamicResource or StaticResource is used, the ContextMenu is created when the resource dictionary is loaded not when the menu is opened.
ContextMenus are very dynamic in that you can manipulate them using data binding or code and the changes immediately take effect.
In most cases you should update your ContextMenu using data bindings, not in code.
Completely replacing menus can be done with code, triggers, or DynamicResource.
If contents must be loaded into RAM only when the menu is open, they can be loaded from a separate file in the Opened event and cleared out in the Closed event.

Categories

Resources