Is there a way to have a toolbar (stock/custom) which aligns all buttons together to one side, say, left?
I have 3 buttons, a,b,c on toolbar. If i dynamically make b hidden, then there is a visible gap between a and c. How can I have a toolbar which automatically closes gap between a and c together, but restores the order when b becomes visible again?
Thanks!
Info
I have tried <Toolbar />, <Stackpanel />, <DockPanel /> so far, but they did not align the buttons.
You need to make b Collapsed instead of Hidden
Refer to MSDN UIElement.Visibility Property:
In the WPF model, Hidden denotes a visibility state where the object
should not render, but should still occupy space in a WPF layout.
And more specific, as #Nayan pointed out, can refer to Visibility Enumeration:
Collapsed Do not display the element, and do not reserve space for it in layout.
Hidden Do not display the element, but reserve space for the element in layout.
Visible Display the element.
PS: That is why for BooleanToVisibilityConverter:
The Convert method returns Visibility.Visible when true is passed in or Visibility.Collapsed when false is passed in.
Use a StackPanel:
<StackPanel Orientation="Horizontal">
<Button Width="100" Click="Button_Click" />
<Button Width="100" Click="Button_Click" />
<Button Width="100" Click="Button_Click" />
<Button Width="100" Click="Button_Click" />
</StackPanel>
private void Button_Click(object sender, RoutedEventArgs e)
{
((Button)sender).Visibility = Visibility.Collapsed;
}
Related
Recently I had been looking for a way to make the tabs in a TabControl editable and came across This example on telerik's website. That did exactly what I wanted but it got me thinking about a similar usage for buttons. I was wondering if it would be possible to use something like that and make a button that would show a textbox instead of the content presenter when say, you right click the button? I tried to make something like this work but so far have only ended up with a blank button.
<Button x:Name="SB" Height="222" Width="222" Click="SB_Click">
<ContentControl.ContentTemplate>
<DataTemplate>
<local:SuperButton Content="{Binding Path=x, Mode=TwoWay}"/>
</DataTemplate>
</ContentControl.ContentTemplate>
</Button>
Where x is a string variable and using the code behind from the link above (with a class name change, of course).
edit: This button will be in an itemscontrol, so I don't think naming the inner elements in xaml will work, but I do like the ease of Wolfgang's answer.
The WPF Content Model is really flexible and allows literally anything inside anything.
This is perfectly valid XAML:
<Button>
<TextBox/>
</Button>
Or even:
<Button>
<MediaElement Source="C:\Videos\WildLife.wmv"/>
</Button>
You can simply host a (e.g.) label (TextBlock) with the text AND a TextBox inside the Button and set their Visiblity properties.
That way, if you right click the button, the TextBox shows up.
<Button>
<Grid>
<TextBox Text=normal button caption" x:Name="label" />
<TextBox
x:Name="textbox"
Text="visible on right click"
MouseRightButtonDown="HandleRightClick"/>
</Grid>
</Button>
And then in your C# code create an event handler to set the Visiblity correctly.
void HandleRightClick(object sender, MouseButtonEventArgs e)
{
label.Visibility = Visibility.Collapsed;
textBlock.Visibility = Visibility.Visible;
}
I use RibbonControlsLibrary. How to align one RibbonGroup to the right? It should be only one group in tab. All other groups should be aligned to the left.
You cannot align the RibbonGroup to the right. The Ribbon doesn't provide the ability to do this.
What you can do is to align page header items... but I don't know if it's enough for you:
DevExpress
I had the same issue, and I finally found something to do this :
I have 3 RibbonGroupBox. Groupe1 may be aligned on left, Groupe3 may be aligned on right. Groupe2 is just an empty RibbonGroupBox I inserted between Groupe1 and Groupe3.
Code XAML :
<Fluent:Ribbon DockPanel.Dock="Top" Title="{x:Static p:Resources.MiseEnBarre}" x:Name="mainRibbon">
<Fluent:RibbonTabItem x:Name="MainMenu" Header="{x:Static p:Resources.MainMenu}" SizeChanged="MainMenu_SizeChanged">
<Fluent:RibbonGroupBox x:Name="Groupe1">
<Fluent:Button x:Name="autoNest" SizeDefinition="Large" LargeIcon="img\image_bar_Nesting.png" Header="{x:Static p:Resources.MenuAutoNest}" Click="AutoNest_Click" />
<Fluent:Button x:Name="saveFile" SizeDefinition="Large" LargeIcon="img\image_save.png" Header="{x:Static p:Resources.MenuSauvegarder}" Click="Sauvegarder_Click" />
</Fluent:RibbonGroupBox>
<Fluent:RibbonGroupBox x:Name="Groupe2">
</Fluent:RibbonGroupBox>
<Fluent:RibbonGroupBox x:Name="Groupe3">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=AvailableCNClist}" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="1" Text="{Binding Path=AvailableCNClist2}" HorizontalAlignment="Right"/>
</Grid>
</Fluent:RibbonGroupBox>
</Fluent:RibbonTabItem>
</Fluent:Ribbon>
Then to manage the Windows redimensioning, I add on my main window the event SizeChanged="MainWindow_SizeChanged" (In the case your RibbonGroupBox dimensions could also change, just add the same event on them).
private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e)
{
UpdateAlignRibbon();
}
private void UpdateAlignRibbon()
{
Groupe2.Width = MyWindow.ActualWidth - Groupe1.ActualWidth - Groupe3.ActualWidth;
}
In my case the Groupe3 RibbonGroupBox may change of dimension, so I call UpdateAlignRibbon() from 3 points :
After Initialization of my window(including defining the GroupBoxes content)
When the MainWindow has its dimensions changed
When Groupe1 or Groupe3 have its dimensions changed
Rover, You can try add RibbonGroup between last left RibbonGroup and Right align RibbonGroup and assign size to newly added ribbon related to window size.
example <RibbonGroup Width="400"></RibbonGroup>
it's looks following image
You can sort of hack in alignment but I'd recommend against it.
<r:RibbonGroup Header="This is a Filler Header With No Functionality but to Take Up Space" Visibility="Hidden">
<s:RibbonButton2/>
<s:RibbonButton2/>
<s:RibbonButton2/>
<s:RibbonButton2/>
</r:RibbonGroup>
The customer wanted their logo on the ribbon across the top of the page, but the more you add "false" elements to the bar, the quicker "true" elements will collapse when shrinking the window size.
Try this:
<RibbonTab Header="Home" x:Name="rtabHome" FlowDirection="RightToLeft" >
<RibbonGroup Header="Group">
<TextBlock Text="Example"/>
</RibbonGroup>
</RibbonTab>
Works with FlowDirection="RightToLeft".
i have three buttons in my wpf window what is the best way to disable button when clicked and make other two button enabled
<Button Name="initialzeButton"
Width="50"
Height="25"
Margin="460,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Click="initialzeButton_Click"
Content="Start"
Cursor="Hand" />
<Button Name="uninitialzeButton"
Width="50"
Height="25"
Margin="0,0,64,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="uninitialzeButton_Click"
Content="Stop"
Cursor="Hand" />
<Button Name="loadButton"
Width="50"
Height="25"
Margin="0,0,9,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="loadButton_Click"
Content="Load"
Cursor="Hand" />
now i use this way in each button :(
private void uninitialzeButton_Click(object sender, RoutedEventArgs e)
{
this.uninitialzeButton.IsEnabled = false;
if (!this.initialzeButton.IsEnabled)
{
this.initialzeButton.IsEnabled = true;
}
if (!this.loadButton.IsEnabled)
{
this.loadButton.IsEnabled = true;
}
}
What is your definition of 'best way'? Is it quick and few lines of code or elegant or..
Several ways come into my mind:
- Use MVVM Light: 1 relaycommand for the three buttons, 3 dependency objects (properties in the viewmodel) for isEnabled which will all be set to false, only set isEnabled to true for the button clicked (which could be sent as a parameter in the relaycommand).
- Use booleanconverters/booleaninverterconverters on the isEnabled property.
- Restyle radiobutton to look like a button, replace the three buttons with a radiobutton group. When one radiobutton is selected, the other ones will be deselected, style them as disabled. Prevent deselected items from being clicked.
Regards,
Michel
you can do somthing like this on page load -
PostBackOptions postBackOptions = new PostBackOptions(Button1);
Button1.OnClientClick = "this.disabled=true;";
Button1.OnClientClick += ClientScript.GetPostBackEventReference(postBackOptions);
For a pure XAML solution wrap them in a style stripped ListBox and tie the click to selection, and selection to disabled state.
I am trying to create UI from XAML at runtime, with something like
private void Application_Startup (object esender, StartupEventArgs e)
{
this.RootVisual = (UIElement)(XmlReader.Load(e.InitParams["Xaml"])
If I feed it this XAML:
<Canvas
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls">
<StackPanel>
<TextBox Width="120" Margin="8" Text="Edit Me" />
<CheckBox Margin="8">Normal</CheckBox>
<ComboBox Margin="8" Width="120" SelectedIndex="1">
<ComboBoxItem Content="First Normal Item" />
<ComboBoxItem Content="Second Normal Item" />
</ComboBox>
</StackPanel>
</Canvas>
then the check box and list behave as expected, but my TextBox does not respond to typing, it stays with its initial value.
The really weird (to me) part is that if I put a handler for KeyDown on to the RootVisual, and in there display a message box, it works. If I have an empty handler or no handler it doesn't.
Do I need to set up some explicit handling for some events? If so, which ones, and how do I handle them?
Upadate: as suggested, I tried putting the dynamic markup into the MainPage of a new app, like this:
public MainPage()
{
InitializeComponent();
var dynamic = XamlReader.Load(xaml);
this.LayoutRoot.Children.Add(dynamic as UIElement);
}
where xaml is a string literal containing the content as above, and everything else is just how VS2010 wizard left it. That works. But I can't see what the effective difference is.
Update update: that's a red herring; the difference is the environment. It works in VS, but not in the Silverlight ActiveX control that I am using in the real app.
Did you define the root namespace on your root element?
<param name="initParams" value="xaml=<TextBox xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Text='hi'/>" />
Just a shot in the dark here, but have you tried adding the dynamically created content as the child of a static "MainPage.xaml" Grid instead of as RootVisual?
Check for IsEnabled="True" property in your main XAML file, if it is set to false then controls will not be editable.
I'm trying to implement "Mega Menu" style menus using WPF. To see examples of mega menus in web design, see here.
So far, I've tried creating a similar interface by using TextBlocks as the highest level of the menu, and then using the mouse hover event to display an additional window that appears positioned below the text block. This is cumbersome and inflexible, future changes would require adding/removing TextBlocks dynamically.
I have considered using the WPF Menu control, because I know the styles can be dramatically modified, but I haven't seen any way to produce multi-column layouts with the hierarchical model that the Menu control uses.
Is there a better way to do this? Am I going to have to stick with custom windows and relative positioning? Can someone point me to an example of this that has already been implemented?
Instead of using custom Windows and positioning, you could use a Popup control. Your can use the StaysOpen=false setting to have it close when the user clicks off-screen.
If you can settle for clicking a menu item instead of hovering, the following custom control will work:
[TemplatePart(Name="PART_HoverArea", Type=typeof(FrameworkElement))]
[TemplatePart(Name="PART_Popup", Type=typeof(Popup))]
public class MegaMenuItem : HeaderedContentControl
{
private FrameworkElement hoverArea;
private Popup popup;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Unhook old template
if (hoverArea != null)
{
hoverArea.PreviewMouseUp -= ShowPopupOnMouseDown;
}
hoverArea = null;
popup = null;
if (Template == null)
return;
// Hook up new template
hoverArea = (FrameworkElement)Template.FindName("PART_HoverArea", this);
popup = (Popup)Template.FindName("PART_Popup", this);
if (hoverArea == null || popup == null)
return;
hoverArea.PreviewMouseUp += ShowPopupOnMouseDown;
}
private void ShowPopupOnMouseDown(object sender, MouseEventArgs e)
{
popup.PlacementTarget = hoverArea;
popup.Placement = PlacementMode.Bottom;
popup.StaysOpen = false;
popup.IsOpen = true;
}
}
You would need a style to display it - something like this. Note the PART_ template part names:
<Style TargetType="WpfApplication14:MegaMenuItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="WpfApplication14:MegaMenuItem">
<Grid>
<Border Name="PART_HoverArea" Background="#fb9c3b" BorderBrush="White" BorderThickness="0,0,1,0">
<ContentPresenter Content="{TemplateBinding Header}" />
</Border>
<Popup
Name="PART_Popup"
PlacementTarget="{Binding ElementName=HoverArea}"
>
<Border MinWidth="100" MaxWidth="400" MinHeight="40" MaxHeight="200" Background="#0d81c3">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The XAML for your menu would then be:
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<WpfApplication14:MegaMenuItem Header="Parent 1">
<WrapPanel Margin="5">
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
</WrapPanel>
</WpfApplication14:MegaMenuItem>
<WpfApplication14:MegaMenuItem Header="Parent 2">
<WrapPanel Margin="5">
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
<TextBlock Text="Put any content you want here" Margin="5" />
</WrapPanel>
</WpfApplication14:MegaMenuItem>
</StackPanel>
Making the menu appear on hover is much harder, because of the way Popups steal focus (you can show the menu, but you can't easily hide it if they mouse over another menu). For that a custom window might work better.
You could use a HeaderedItemsControl and swap out the Panel to suit your needs; by default it uses a StackPanel however a WrapPanel may suit you better. The pop out and mouse over behavior do not exist by default and would need to be implemented.
A more robust approach would be to leverage a custom Expander; as it provides the pop out behavior you are after and the linked to walkthrough provides the mouse over behavior.
I wonder if the Ribbon control can be retrofitted to do this? It provides tabs, labels, columns and all that.
Please use this UI design sparingly and make sure that it only opens and closes when the user specifically requests such. It's tremendously annoying when a popup mega-menu appears over a website I'm viewing, and I can't get it to close, except for when I want to click on it and it goes away.
Custom windows and relative position are essentially how the WPF Menu/MenuItem control works... but as you've found, it's non-trivial. Best bet would be to retemplate the Menu/MenuItem controls to meet your need.