 |
|

|
Very Good.
How do I add child MenuItems programatically in mvvm?
|
|
|
|

|
Don't wander in the WPF arena very often but was looking for just such a control.
Thanks
A girl phoned me and said, 'Come on over. There's nobody home.' I went over. Nobody was home! Rodney Dangerfield
|
|
|
|

|
Good article - very useful bit of code.
|
|
|
|

|
This is great control. Took only a short time to convert to Visual Studio 2010 and integrate the SplitButton in a test project.
Thanks a lot!
Best regards Anders.
|
|
|
|

|
Really easy to use and implementation is great.
|
|
|
|

|
Hi:
There's something strange with this control. The demo works as described, but when I use it in other project following the instructions, the button displays only a blank rectangle in design mode and when running doesn't show at all. I am using VS 2010, migrated the project to Framework 4.0.
The strange thing is that I inserted the demo project in my new project and there the splitbutton is shown correctly.
|
|
|
|

|
sounds like a problem with the styles in the xaml-files, sure you have inserted them into your project corretly?
I'm also using VS2010 with .Net4, no Problems at all
|
|
|
|

|
hi,
i found out that i can only add VistaSplitButtonStyle as style,
how bout the other, since i need it to match my other normal button
thanks
|
|
|
|
|

|
I have made 2 fixes related to databinding:
If menu items are data bound (like here[^]), one issue is that context menu placement properties are not applied (because ContextMenu instance is not created as part of EnsureContextMenuIsValid method).
Modified EnsureContextMenuIsValid method whis fixes this:
private void EnsureContextMenuIsValid()
{
if (this.ContextMenu == null)
{
this.ContextMenu = new ContextMenu();
}
this.ContextMenu.PlacementTarget = this;
this.ContextMenu.Placement = Placement;
this.ContextMenu.Opened -= ((sender, routedEventArgs) => IsContextMenuOpen = true);
this.ContextMenu.Closed -= ((sender, routedEventArgs) => IsContextMenuOpen = false);
this.ContextMenu.Opened += ((sender, routedEventArgs) => IsContextMenuOpen = true);
this.ContextMenu.Closed += ((sender, routedEventArgs) => IsContextMenuOpen = false);
}
2nd issue is which occurs also with databinding. if (!ContextMenu.HasItems)check in OnDropDown method was evaluated to false when items were data bound (but only in some scenarios) and menu was not shown. So I have removed this check.Martin Pozor (pozi)
|
|
|
|

|
Excellent control, thank you.
However, there is one issue. ButtonChrome should render as pressed not only when context menu is open, but also when mouse is pressed on the button (like regular button). Currently clicking on button (in Split and Button modes) provides no visual feedback to user.
Following XAML snippet inserted into ControlTemplate.Triggers section fixes the issue:
For all themes except Classic and Vista:
<Trigger Property="IsPressed" Value="true" >
<Setter Property="RenderPressed" Value="true" TargetName="buttonChrome" />
</Trigger>
For Classic theme:
<Trigger Property="IsPressed" Value="true">
<Setter Property="BorderStyle" TargetName="buttonChrome" Value="RaisedPressed"/>
</Trigger>
For Vista theme:
<Trigger Property="IsPressed" Value="True">
<Setter Property="Style" TargetName="outerBorder1" Value="{StaticResource outerBorderPressed}"/>
<Setter Property="Style" TargetName="innerBorder1" Value="{StaticResource innerBorderPressed}"/>
<Setter Property="Style" TargetName="outerBorder2" Value="{StaticResource outerBorderPressed}"/>
<Setter Property="Style" TargetName="innerBorder2" Value="{StaticResource innerBorderPressed}"/>
</Trigger>Martin Pozor (pozi)
modified on Wednesday, February 24, 2010 3:47 PM
|
|
|
|

|
Essential fix to this great control. Thanks!
|
|
|
|

|
Thank you for this really great control! I have used the example code to set an image in my SplitButton using a StackPanel, but I am not clear on how to use the Icon property for the MenuItems. I've tried setting Icon="Resources\icon.png" which is the same file I use in my stackpanel image but it renders the text instead of the image.
I am using Blend 3 and would like to make sure this is all done within the XAML.
|
|
|
|

|
I figured it out thanks to a little help from this article
http://www.a2zdotnet.com/View.aspx?id=92
<Wpf_Controls:SplitButton Height="30" x:Name="btnsName" Width="86" Click="btnsName_Click" Mode="Split" Placement="Bottom" HorizontalAlignment="Left" Margin="8,141,0,0" VerticalAlignment="Top">
<Wpf_Controls:SplitButton.Content>
<StackPanel Orientation="Horizontal">
<Image x:Name="img_Name" Source="Resources\Image.png" Width="17" Height="18"/>
<TextBlock Text="Button Name" Margin="3,0,0,0"/>
</StackPanel>
</Wpf_Controls:SplitButton.Content>
<MenuItem Header="Menuitem 1" Click="btnsName_Menuitem1_Click">
<MenuItem.Icon>
<Image Source="Resources\Image1.png" Width="17" Height="18"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menuitem 2" Click="btnsName_Menuitem2_Click">
<MenuItem.Icon>
<Image Source="Resources\Image2.png" Width="17" Height="18"/>
</MenuItem.Icon>
</MenuItem>
</Wpf_Controls:SplitButton>
|
|
|
|
|

|
It isn't his job to support you. Be glad he has contributed a very useful article, source code for the control and an easy to understand demo application. If you cant figure it out from there - you really shouldn't be programming.
|
|
|
|

|
Hello
The selected item does not display in the button.
:(
|
|
|
|

|
Nice job on this control--I really like it.
I've got a question on using the control on a toolbar. Out-of-the-box WPF buttons take on toolbar button styling when placed in a toolbar control. However, this button retains its default styling--no toolbar button styling.
Am I missing a property setting to get this button to show toolbar styling? I'd add a user wish-list request for the button to automatically take on toolbar button styling when placed in a toolbar.
Again, nice job and thanks.
David Veeneman
www.veeneman.com
|
|
|
|

|
Congratulations, it's really nice!
I really need to have the items in the drop down databound. Is there any chance of you adding ItemsSource and ItemTemplate?
Good job!
Pete
|
|
|
|

|
I would like to add additional child menu items during runtime using code, and not upfront in XAML.
For example, Child1 and Child2 below will be added to XAML defined structure during runtime based on a given event:
Main
--Sub1
----Child1
----Child2
--Sub2
--Sub3
Is this possible?
|
|
|
|

|
I meet the same problem too.
And I add the following new method to the SplitButton class to solve it.
public void UpdateContextMenu(MenuItem item1)
{
EnsureContextMenuIsValid();
this.ContextMenu.Items.Add(item1);
}
In your program,
SplitButton btn1 = new SplitButton();
MenuItem m1=new MenuItem();
m1.Header = "sub1";
MenuItem m1_1 = new MenuItem();
m1_1.Header = "sub1_1";
m1.Items.Add(m1_1);
MenuItem m2 = new MenuItem();
m2.Header = "sub2";
btn1.UpdateContextMenu(m1);
btn1.UpdateContextMenu(m2);
|
|
|
|

|
Is possible use this control in Silverlight 2? Add the reference is not possible beacause it's debug for wpf. I'm searching a workaround to use the splitbutton in Silverlight..any idea or someone know this control created for Silverlight??
|
|
|
|

|
Thanks man!
A train station is where the train stops. A bus station is where the bus stops. On my desk, I have a work station....
_________________________________________________________
My programs never have bugs, they just develop random features.
|
|
|
|

|
Thanks for posting this article. I really like it.
I'm using this with vs2008, SP1 and I'm having a couple problems.
1. The SplitButton project has a reference to Microsoft.Windows.Design.Markup which is not found on my system, but it doesn't seem to prevent me from running the demo.
2. I tried changing the mode to Dropdowm (see below) from the default Split and when I click anywhere on the button, nothing drops down.
<m:SplitButton Mode="Dropdown" Margin="0,1,0,1" Padding="5,0,5,0" Placement="Bottom" HorizontalAlignment="Center" VerticalAlignment="Center" Height="24" Click="SplitButton_Click"
Style="{DynamicResource {x:Static m:SplitButtonResources.VistaSplitButtonStyleKey}}">
<m:SplitButton.Content>
<StackPanel Orientation="Horizontal">
<Image Source="Icons\mail.ico" Width="16" Height="16"/>
<TextBlock Text="Send/Receive" Margin="3,0,0,0"/>
</StackPanel>
</m:SplitButton.Content>
<MenuItem Header="Send and receive _all"/>
<MenuItem Header="Receive All"/>
<MenuItem Header="Send All"/>
<Separator/>
<MenuItem Header="Hotmail (Default)"/>
<MenuItem Header="Gmail"/>
</m:SplitButton>
|
|
|
|

|
I figured out one way to make it behave as a true dropdown with the left click. Just modify your application's click handler for the button as follows:
private void SplitButton_Click(object sender, RoutedEventArgs e)
{
if (((SplitButton)sender).Mode == SplitButtonMode.Dropdown)
{
((SplitButton)sender).ContextMenu.PlacementTarget = (SplitButton)sender;
((SplitButton)sender).ContextMenu.IsOpen = true;
e.Handled = true;
return;
}
|
|
|
|

|
Hi ssing
thanks for pointing out the bug, I haven't looked at this for a while,
I'm surprised no one else has spotted the error, possibly no one uses it in DropDown Mode,
anyway I've uploaded a fix to codeproject.
thanks again.
Alan...
|
|
|
|

|
Very nice control, thanks for sharing it!
When I first tested the SplitButton control, my instinct was to click the drop-down button to open the context menu (so I could see the available items), then click it again to close it. I was surprised to discover that this sometimes resulted in the default click event getting fired (showing the "Click event handler" dialog). I realized this happened when the mouse pointer hotspot is directly over the "path" Path object. In this case the Path object named "path" receives the click and passes it to the underlying default button rather than the drop-down button the user intended. This is easily fixed by declaring the "path" Path object *before* the drop-down button in the XAML rather than after (thus placing it lower in the Z order). If you do that, I don't think you even need the MouseOver Trigger that sets the "path" Path's Visibility=Collapsed.
I would still like to figure out how to get the drop down menu to close when you click the drop-down button when the menu is already open, but haven't figured out a good way to accomplish this, any suggestions?
|
|
|
|

|
Hi matt,
thanks for your comments,
I've updated the code to include your suggestions for the z-order of the path object, this seems to have fixed the bug you described,
I've also implemented the feature to close the context menu if open when clicking the button for a second time.
Regards
Alan...
|
|
|
|

|
That's great! Where can I get the updated code? The link at the top of the project page still seems to be the old version.
|
|
|
|

|
I've uploaded it today, I think it can take a day or two to update on the site.
|
|
|
|
|

|
Hi all, this is my first post so be kind
When using this control in a "button bar" type menu I found myself needing a version of the control that had the same Vista style but fuctioned like a normal button (without the drop-down/split).
I made a few simple changes to the code to allow a "Button" mode to be set which removes the split/dropdown from the control.
I know one could just create a new Vista style based on the current style and remove the dropdown portion. Doing so however, would require maintaining two copies of the main style components and make style changes/tweaking more cumbersome.
So here are the changes: (These only affect the Vista style!)
SplitButton.cs
I added the Button value to the enum as follows
public enum SplitButtonMode
{
Split, Dropdown, Button
}
Vista.xaml
I changed the Width="16" to Width="Auto" in the second ColumnDefinition and added the width to outerBorder2. This allows outerBorder2 to be collapsed taking the width of 16 with it.
<ControlTemplate TargetType="{x:Type local:SplitButton}">
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
...
<!---->
<Border x:Name="outerBorder2" Width="16" Margin="-1,0,0,0" Grid.Column="1" Style="{DynamicResource outerBorderNormal}">
<Border x:Name="innerBorder2" Style="{DynamicResource innerBorderNormal}"/>
</Border>
Finally I added a new trigger for the "Button" mode to the end of ControlTemplate.Triggers.
<Trigger Property="Mode" Value="Button">
<Setter Property="Visibility" TargetName="PART_DropDown" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="outerBorder2" Value="Collapsed"/>
</Trigger>
Well that's it. Now you can set Mode="Button" on the SplitButton control and a normal button using the same Vista style will result.
|
|
|
|

|
When I put this splitbutton in a toolbar, it still looks like a regular button on a form. Any other buttons on the same toolbar look like differently on my XP Pro machine. (They look like labels, until you hover on them, then they turn blue with a border.) Do you know of a way to instruct this to use the style that toolbar uses to render a normal button. Code would look something like this to see the difference: <Grid> <ToolBar VerticalAlignment="Top"> <Button Content="Hello"/> <m:SplitButton Content="Split Button"/> </ToolBar> </Grid> I sure would appreciate any of your thoughts on the matter.
|
|
|
|

|
Could you turn this into a drop button?
Dim SomethingAboveMyHead As LightBulb
|
|
|
|

|
I thought this would be achieved by using DropDown mode. However, it is not quite right because left click on mouse does nothing. Drop-down only appears for right click on Mouse. Am still trying to finger out how to modify to become a standard left click drop down button.
Regards John S
|
|
|
|

|
Not like that: like the ToolStripDropDownButton in WinForms.
Dim SomethingAboveMyHead As LightBulb
|
|
|
|

|
John,
Have you figured out how to turn this into a standard left-click drop down button? I'm looking to solve the same problem. Thanks!
|
|
|
|

|
Unfortunately I didn't because moved on to other UI issues.
|
|
|
|

|
This is probably way past being useful to you by now but I did figure out a way to make it behave as a true dropdown with left click. Just change the click handler in your application as follows:
private void SplitButton_Click(object sender, RoutedEventArgs e)
{
if (((SplitButton)sender).Mode == SplitButtonMode.Dropdown)
{
((SplitButton)sender).ContextMenu.PlacementTarget = (SplitButton)sender;
((SplitButton)sender).ContextMenu.IsOpen = true;
e.Handled = true;
return;
}
|
|
|
|

|
Hi,
I tried to place your Splitbutton inside a Toolbutton.
Its firing error as,
The assembly used when compiling might be different than that used when loading
and the type is missing. Error at object 'System.Windows.Controls.ToolBar' in markup file
Do you have any idea about this error message?
|
|
|
|

|
I really like this control and want to use it, but I would prefer to merge it into an existing project rather than having it in a project of its own.
I copied the Themes folder and the other three files to a sub-folder in another project. I changed all of the namespaces to match my current project and added the necessary references.
The Problem: I was able to add and configure a new SplitButton to a WPF Window, but the button is not visible at design or run time. I can see the outline of the button when I select the button's XAML code, but that's it. The project compiles fine.
Any ideas on what the problem might be? Your help would be greatly appreciated.
Thanks,
Joe Puccia
|
|
|
|

|
Hello Joe,
Just to let you know that I faced the same problem and found a solution.
Check this blog entry: http://wangmo.wordpress.com/2007/09/27/themesgenericxaml/[^]
Checklist:
- Copy the themes to a folder "Themes" in your application
- Change all theme .xaml files, by updating the reference to your assembly to something like
xmlns:local="clr-namespace:TheNamespaceWhereTheControlIsLocated"
- Change resource dictionary merge in file generic.xaml like this:
<ResourceDictionary Source="component/themes/Vista.xaml"/>
- Change the assembly info so that you get the resource dictionaries from the source assembly
[assembly: ThemeInfo(
ResourceDictionaryLocation.SourceAssembly, ResourceDictionaryLocation.SourceAssembly)]
Hope it helps
Cheers,
- xico -
|
|
|
|

|
Hi I've downloaded your sample
But On my maschine I can trun it:
Error 1 The name 'InitializeComponent' does not exist in the current context C:\Dokumente und Einstellungen\hkl\Desktop\SplitButton\SplitButton\Demo\Window1.xaml.cs 13 13 Demo
Can you upload a running version for WinXP?
Best regards
|
|
|
|

|
Hi Horst
This control was developed and uploaded from a windows xp machine, so i don't think that is the problem.
unfortunately i don't have vs2005, the project was written using the VS2008 beta 2 bits.
I assume you have the WPF extensions for vs2005 installed and the dotnet framework 3.0, if so then I don't really know how else to help you.
regards
Alan
|
|
|
|

|
Hi Alan
Thanks for the swift feedback.
Yes, I have installed all the nessasary WPF extensions and the 3.0 framework.
I'm working on a WPF application
Good to know, you use also a XP machine.
Well, I don't have time at the moment to find the reason why it's not working with VS2005. Do you uses framework 3.5 features?
@any other readers: Who can run the sample with VS2005?
Best regards
Horst
|
|
|
|

|
Hi Horst
Horst Klein wrote: Do you uses framework 3.5 features?
No. both the demo and SplitButton project's target framework are set to 3.0
Are all the PresentationFramework references in place.
you should have references for
PresentationCore
PresentationFramework
PresentationFramework.Aero
PresentationFramework.Classic
PresentationFramework.Luna
PresentationFramework.Royale
in both projects
regards
Alan
-- modified at 13:27 Friday 23rd November, 2007
|
|
|
|

|
This looks well done and I'm sure there is a lot that I can learn by reading what is here. Given that most of the functionality of your control is provided within the Theme and DemoStyle XAMLs, might I suggest putting some comments in these files to make them more readable?
|
|
|
|

|
Hello. Firstly, thanks for sharing the SplitButton control. It is very useful! But I found two bugs : 1. In the SplitButton.cs (line 137), "s.ContextMenu.HorizontalOffset = (double)e.NewValue;" must be replaced by "s.ContextMenu.VerticalOffset = (double)e.NewValue;" 2. In the Vista theme, there is a strange bug. I don't explain it. Here is how to reproduce it: <Border Height="30"> <StackPanel Orientation="Horizontal"> <m:SplitButton Margin="0,1,0,1" Padding="5,0,5,0" Placement="Bottom" HorizontalAlignment="Center" VerticalAlignment="Center" Height="24" Style="{DynamicResource {x:Static m:SplitButtonResources.VistaSplitButtonStyleKey}}"> <m:SplitButton.Content> <StackPanel Orientation="Horizontal"> <Image Source="Icons\mail.ico" Width="16" Height="16"/> <TextBlock Text="Send/Receive" Margin="3,0,0,0"/> </StackPanel> </m:SplitButton.Content> <MenuItem Header="Send and receive _all"/> <MenuItem Header="Receive All"/> <MenuItem Header="Send All"/> <Separator/> <MenuItem Header="Hotmail (Default)"/> <MenuItem Header="Gmail"/> </m:SplitButton> <m:SplitButton Margin="0,1,0,1" Padding="5,0,5,0" Placement="Bottom" HorizontalAlignment="Center" VerticalAlignment="Center" Height="24" Style="{DynamicResource {x:Static m:SplitButtonResources.VistaSplitButtonStyleKey}}"> <m:SplitButton.Content> <StackPanel Orientation="Horizontal"> <Image Source="Icons\mail.ico" Width="16" Height="16"/> <TextBlock Text="Send/Receive 2" Margin="3,0,0,0"/> </StackPanel> </m:SplitButton.Content> <MenuItem Header="Send and receive _all"/> <MenuItem Header="Receive All"/> <MenuItem Header="Send All"/> <Separator/> <MenuItem Header="Hotmail (Default)"/> <MenuItem Header="Gmail"/> </m:SplitButton> </StackPanel> </Border> In the second SplitButton, the "path" is not rendered and the DropDown button doesn't open the context menu. If anyone have an idea? Thanks very much. Cyber Sinh
|
|
|
|

|
Hi Cyber
Cyber Sinh wrote: 1. In the SplitButton.cs (line 137), "s.ContextMenu.HorizontalOffset = (double)e.NewValue;" must be replaced by "s.ContextMenu.VerticalOffset = (double)e.NewValue;"
Doh!!, I'll have to be more careful when using Copy & Paste
Cyber Sinh wrote: 2. In the Vista theme, there is a strange bug. I don't explain it. Here is how to reproduce it:
This was a strange one, I changed a few StaticResource's to DynamicResources which seems to have fixed the problem, (not sure why though?).
I've uploaded an update with the fixes
Let me know if you find anymore.
Thanks again Cyber.
Alan...
|
|
|
|
 |