How to add additional attributes to standard XAML elements? - wpf

This button click method launches a Window called "(assemblyname).Reports" when a button with Content "Reports" is clicked:
private void Button_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)e.OriginalSource;
Type type = this.GetType();
Assembly assembly = type.Assembly;
Window window = (Window)assembly.CreateInstance(String.Format("{0}.{1}", type.Namespace, button.Content));
window.ShowDialog();
}
But I want the Content attribute value of the button to be able to change, e.g. it might change to "Stock Reports" but I still want the clicking of the button to launch "(assemblyname).Reports".
Is there a way to add attributes to the button tag, e.g. "TheWindowFileName"?
<Button x:Name="btnReports" Content="Stock Reports" TheWindowFileName="Reports"/>
If not, how else can I add additional information to my button elements which I can read and process in code behind?

Certainly you can use attached properties to add extra attributes to XAML elements, but for what you need you could probably just use the existing Tag property:
<Button x:Name="btnReports" Content="Stock Reports" Tag="Reports"/>

Using Attached Property here can be an overkill but instead you can try to encapsulate your button behavior in a Command and pass the data you want to use in the command as a CommandParameter. That should do the trick.

Related

How do I get the UI object inside of a content presenter?

I have an ItemsControl displaying a list via binding. The list is of a ViewModel type which is then referenced in a DataTemplate to display a button. The button has it's UID bound to a GUID from the the view model. When a new view model is added to the bound list, I need to get hold of the button that will be added, as the buttons need to be able to be dragged/dropped by the user. At the moment the closest I can get is finding the ContentPresenter that displays the button, but the content of that ContentPresenter is of type view model.
Is there a way to find the button that has been added? Or should I not used a DataTemplate and create the buttons my self in order to access them?
I have used the VisualTree helper to get the content presenter, but have not managed to find the button.
You could handle the Loaded event for the Button:
<DataTemplate>
<Button Loaded="OnButtonLoaded" ... />
private void OnButtonLoaded(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
//...
}
You won't be able to get a reference to it using the VisualTreeHelper until it has actually been added to the visual tree and loaded anyway.

Having a clickable element in accordion header

I have a checkbox inside of the accordionitem's header. However, when I click a checkbox, it collapses or expands the accordionitem. Is there a way to click the checkbox without the accordion expanding/collapsing?
found similar problem, different context here.
For my particular case:
in xaml we add click event to the checkbox
<Accors:AccordionItem>
<Accors:AccordionItem.Header>
...
<CheckBox Click="CheckBox_Click_1"/>
...
</Accors:AccordionItem.Header>
</Accors:AccordionItem>
and in the code behind:
private void CheckBox_Click_1(object sender, RoutedEventArgs e)
{
e.Handled = true;
}
Try to change Accordion.SelectionMode property to all available enums. I had faced the same problem working with accrodion but it got resolved when i changed property value to None or some other available enum.
If the Header content contains any controls then ensure that the selection mode is ZeroOrMore
SelectionMode="ZeroOrMore"

Two Ribbon buttons pointing to same View Model

I have a Module,Within the module .I need two Ribbon buttons "Create" and "Edit".Both these buttons point same View and ViewModel.The only way i can distinguish these is using the command parameter property part of Ribbon Button.I am using Navigate View to move to the View.I want to pass additional parameter to ViewModel constructor saying the invoke is from Create or Edit.Any suggestions??
RibbonButton has a Tag property:
http://msdn.microsoft.com/en-us/library/microsoft.windows.controls.ribbon.ribbonbutton.ASPX
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.tag.ASPX
When defining the buttons, you can set Tag property for each ribbon button. You can then extract Tag value in your event handler and react accordingly.
I would bind Create and Edit buttons two different Commands e.g. CreateCommand and EditCommand. I would pass any additional details about the caller in the corresponding Execute methods of the Command.
Sample Code:
void CreateCommandExecute(object o)
{
YourMethod("Create", o);
}
void EditCommandExecute(object o)
{
YourMethod("Edit", o);
}
void YourMethod(string caller, object commandParameter)
{
// Your logic goes here
}
You need create two diferentes Commands in your ViewModel:
1- CommandEdit --> Asingned the CommandProperty button Edit by binding;
2- CommandCreate --> Asingned the CommandProperty button Create by binding.
Is not good idea shared logic in the shame command behavior.

WPF Default Button command not triggering binding in textbox

I have a search screen with some textboxes and a Search button as the default. If I type in a textbox and I CLICK the button, everything's great. But if I press enter within a text box, the button command fires but the binding on whatever text box I was in does NOT fire and so my criteria doesn't make it to the view model to get filtered on.
I know one fix is to set the bindings on the text boxes to PropertyChanged, but this seems like way overkill. I might have logic in the viewmodel doing stuff and I don't want that to trigger on every single keystroke.
What I really want is a way for the button itself to either trigger a focus change or somehow trigger binding. Or to have the textbox trigger binding if focus is lost OR I press enter OR a command is executed from anywhere
One way to do this is with a BindingGroup.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.bindinggroup.aspx
If your TextBox(es) and Button are both contained within a Grid (for example), you would add a BindingGroup like this:
<Grid>
<Grid.BindingGroup>
<BindingGroup Name="bindingGroup1"/>
</Grid.BindingGroup>
Then you could add a Click event handler to your button and call CommitEdit() on the BindingGroup (which the Button and TextBox inherit from the Grid):
private void button1_Click(object sender, RoutedEventArgs e)
{
(sender as FrameworkElement).BindingGroup.CommitEdit();
}
The Button.Click event fires before the CommandBinding, so any databound TextBox or any other databound controls within that BindingGroup should be updated before your view model command gets executed.
I've had the exact scenario you just mentioned. The trick I use is an attached behavior that sits on a control and listens for the PreviewKeyDown event. It checks if enter is being pressed. If so it forces the control to lose focus, thus causing the binding to fire before the command executes.
A simpler approach (rather than using a binding group) is to use the default button's click event to set the focus to itself. As this happens before the command is executed it means the ViewModel is updated in time.
private void button1_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Focus()
}
And if you really hate code behind, you could always write an attached property...

using routed events within Silverlight user controls

within my current project file I have a user control that has a storyboard animation applied to the control. When a button is clicked in the page the storyboard starts and basically visually presents the control to the user. The storyboard resides in the current page as a resource
<navigation:Page.Resources>
<Storyboard x:Name="PreferncesOpen">....</Storyboard x:Name="PreferncesOpen">
</navigation:Page.Resources>
Within the page I have button that I have a click event on that starts the storyboard
private void btnOpenPreferences_Click(object sender, RoutedEventArgs e)
{
preferencesPanel.Visibility = System.Windows.Visibility.Visible;
PreferncesOpen.Begin();
}
Within the userControl (preferencesPanel) I have a button that when clicked needs to close/collapse the user control. I plan to do this using Visibility.collapsed. I assume that I need to use routed commands since the button is within the user control but the actions need to be called within the page that contains the control? I'm still new to routed commands and I assume this is the correct approach. I'm just unsure how to click on a button within the user control and have it modify or execute commands that would impact how the page (in which this control resides) may change or for that part affect other elements within the page? For example when the button is clicked within the user control I would like the visibility of the user control to be set to collapsed. I also would like to have the width of one of the grid columns within the main page re-size. I have done this in the past using the code behind for the page but I am trying to separate some of this and I thought routed commands would be the way to go?
I'd greatly appreciate any tips.
Thank you in advance
The title is a bit misleading, you're asking about commands rather then routed events if I understand you correctly.
Here's an example of using a DelegateCommand<T> from the Prism library; It happens to be my personal preference.
Markup :
<Button x:Name="MyButton" Content="Btn" Command="{Binding DoSomethingCommand}"/>
Code-behind* or ViewModel :
(* if you're not using MVVM make sure to add MyButton.DataContext = this; so you're sure that the button can databind to your code behind effectively)
public DelegateCommand<object> DoSomethingCommand
{
get
{
if(mDoSomethingCommand == null)
mDoSomethingCommand = new DelegateCommand(DoSomething, canDoSomething);
return mDoSomethingCommand;
}
private DelegateCommand<object> mDoSomethingCommand;
// here's where the command is actually executed
void DoSomething(object o)
{}
// here's where the check is made whether the command can actually be executed
// insert your own condition here
bool canDoSomething(object o)
{ return true; }
// here's how you can force the command to check whether it can be executed
// typically a reaction for a PropertyChanged event or whatever you like
DoSomethingCommand.RaiseCanExecuteChanged();
The argument that's passed to the above function is the CommandParameter dependency property (in Prism it's an attached property as well as the Command property if memory serves me right).
When it's set, you can pass a value of your choosing to the command that you wish to execute.
Hope that helps.

Resources