I have the same command that I want to use for two controls on a dialog type window. As potentially interesting background, I'm using Josh Smith's ViewModel / RelayCommand ideas, since I am new to WPF and it's the first thing I've seen that I can actually understand from a big picture point of view.
So the command is a property of a ViewModel, and with the Button's built-in support, it is trivial and painless to bind to the command in the XAML:
<Button ... Command="{Binding Path=PickCommand}" Content="_Ok"></Button>
Now in a ListView, the only way I have gotten to use the same command hooked up to trigger on a double click is by using an event handler:
<ListView ...
ItemsSource="{Binding Path=AvailableProjects}"
SelectedItem="{Binding Path=SelectedProject, Mode=TwoWay}"
MouseDoubleClick="OnProjectListingMouseDoubleClick"
>
private void OnProjectListingMouseDoubleClick(object sender, MouseButtonEventArgs e) {
var vm = (ProjectSelectionViewModel) DataContext;
vm.Pick(); // execute the pick command
}
Is there a way to do this by binding the way the button does it?
Cheers,
Berryl
<------- implementation - is there a better way? --->
Your SelctionBehavior class was spot on, but I was confused at your xaml code. By setting the "Style" on the listViewItem I was getting the children of the DataContext where the command I want to execute lives. So I attached the behavior to the ListView itself:
<ListView ...Style="{StaticResource _attachedPickCommand}" >
And put the style in a resource dictionary:
<Style x:Key="_attachedPickCommand" TargetType="ListView">
<Setter Property="behaviors:SelectionBehavior.DoubleClickCommand" Value="{Binding Path=PickCommand}" />
</Style>
It works! But it 'feels' awkward setting the style property of the list view. Is this just because I am not comfortable with style as more than something visual in wpf or is there a better way to do this?
Cheers, and thanks!
Berryl
Yes there is! You can use attached behaviors and bind the command to that behavior.
public class SelectionBehavior {
public static readonly DependencyProperty CommandParameterProperty=
DependencyProperty.RegisterAttached("CommandParameter", typeof(object), typeof(SelectionBehavior));
public static readonly DependencyProperty DoubleClickCommandProperty=
DependencyProperty.RegisterAttached("DoubleClickCommand", typeof(ICommand), typeof(SelectionBehavior),
new PropertyMetadata(OnDoubleClickAttached));
private static void OnDoubleClickAttached(DependencyObject d, DependencyPropertyChangedEventArgs e) {
var fe=(FrameworkElement)d;
if(e.NewValue!=null && e.OldValue==null) {
fe.PreviewMouseDown+=fe_MouseDown;
} else if(e.NewValue==null && e.OldValue!=null) {
fe.PreviewMouseDown-=fe_MouseDown;
}
}
private static void fe_MouseDown(object sender, MouseButtonEventArgs e) {
if(e.ClickCount==2) {
var dep=(FrameworkElement)sender;
var command=GetDoubleClickCommand(dep);
if(command!=null) {
var param=GetCommandParameter(dep);
command.Execute(param);
}
}
}
public static ICommand GetDoubleClickCommand(FrameworkElement element) {
return (ICommand)element.GetValue(DoubleClickCommandProperty);
}
public static void SetDoubleClickCommand(FrameworkElement element, ICommand value) {
element.SetValue(DoubleClickCommandProperty, value);
}
public static object GetCommandParameter(DependencyObject element) {
return element.GetValue(CommandParameterProperty);
}
public static void SetCommandParameter(DependencyObject element, object value) {
element.SetValue(CommandParameterProperty, value);
}
}
and in the xaml you would need to set a style for a ListViewItem which represents your data in the ListView. Example
<ListView>
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="local:SelectionBehavior.DoubleClickCommand" Value="{Binding Path=DataContext.PickCommand}"/>
<Setter Property="local:SelectionBehavior.CommandParameter" Value="{Binding Path=DataContext}"/>
</Style>
</ListView.ItemContainerStyle>
</ListView>
Here is some more information about the Attached Behavior pattern
Related
I have a ListView with pretty long listelement at times. I would like to create an event, where if I drag the mouse over an element, the whole name appears in a tooltip-like small window with the whole text of the item. This way the user can read it even if it is too long for the ListView window width.
I am a bit stuck, because I find no MouseOver event for the ListView elements. I would probably have to go on with a custom Style for my ListView, but I don't have experience with Styles.
I would really appreciate a little help, to get me started!
Create an AttachedProperty for MouseMove and hook your list view with the property. The attached property can be used to any element in your application.
Attached Property
public class MouseBehaviour
{
public static readonly DependencyProperty MouseMoveCommandProperty =
DependencyProperty.RegisterAttached("MouseMoveCommand", typeof(ICommand), typeof(MouseBehaviour), new FrameworkPropertyMetadata(new PropertyChangedCallback(MouseMoveCommandChanged)));
private static void MouseMoveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = (FrameworkElement)d;
element.MouseMove += new MouseEventHandler(element_MouseMove);
}
static void element_MouseMove(object sender, MouseEventArgs e)
{
FrameworkElement element = (FrameworkElement)sender;
ICommand command = GetMouseMoveCommand(element);
command.Execute(e);
}
public static void SetMouseMoveCommand(UIElement element, ICommand value)
{
element.SetValue(MouseMoveCommandProperty, value);
}
public static ICommand GetMouseMoveCommand(UIElement element)
{
return (ICommand)element.GetValue(MouseMoveCommandProperty);
}
}
XAML
xmlns:mousebehav="clr-namespace:your namespace"
<ListView mousebehav:MouseBehaviour.MouseMoveCommand="{Binding MouseMoveCommand}">
VM
private RelayCommand _MouseMoveCommand;
public RelayCommand MouseMoveCommand
{
get
{
if (_MouseMoveCommand== null) return _MouseMoveCommand= new RelayCommand(param => Execute_MouseMoveCommand((MouseEventArgs)param));
return _MouseMoveCommand;
}
set { _MouseMoveCommand= value; }
}
private void Execute_MouseMoveCommand(MouseEventArgs param)
{
//your logic to expand or ??
}
Thanks for the answer. After a few hours of experimenting, I managed to solve it quite compact from the xaml:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="ToolTip" Value="{Binding Name}" />
</Style>
</ListView.ItemContainerStyle>
I am in the middle of creating WPF utility library but I'm stuck on how to create an easy to use enumeration converter which will help in binding any enumeration to a ComboBox control and when enumeration is declared with [Flags] attribute, ComboBox will contain checkboxes data bound to it. Solution needs to be generic so that it will be easy to use for any enumeration and I suppose it would need fresh pair of eyes of an experienced WPF developer.
So far I've come up with a combination of ObjectDataProvider as a source of enum items and 2 converters, one for ItemsSource and another for SelectedValue.
I used CollectionView as a base class for ItemsSource to use CurrentChanged but it does not work as I tried to raise OnCurrentChanged after the collection has been notified about any CheckBox being checked without converter's ConvertBack being executed.
The problem is that data bound property to which ComboBox SelectedValue property is bound, is not updated unless I'll change the selected item (not tick the checkbox).
I've set IsSynchronizedWithCurrentItem but it did not help.
How to force updating of SelectedValue from data bound object? I have a freedom of choice so the solution might involve custom attached properties, inheriting from ComboBox etc. Being really new to WPF I think although the solution is almost right as it almost works, there can be a simpler way of getting to it.
Another issue would be how to customize text displayed on ComboBox so it will contain aggregated selections of ticked checkboxes.
I uploaded VS2012 project here. The structure of a project resembles real application with resources held separately (for simplicity in App.xaml).
Sorry I have not included any code but there is a lot of code involved.
Below is the XAML declaration for a CheckBox bound to standard enumeration (although enumeration used is with [Flags]), which works fine and further a CheckBox bound to [Flags] enumeration.
<ComboBox ItemsSource="{Binding Source={StaticResource someItemsSource}}"
SelectedValue="{Binding BindToSomeItems}"
Style="{StaticResource enumComboBox}"/>
<ComboBox ItemsSource="{Binding BindToSomeItems, Converter={local:LocalizedFlagsEnumConverter}}"
IsSynchronizedWithCurrentItem="True"
SelectedValue="{Binding BindToSomeItems, Mode=TwoWay, Converter={local:SelectedFlagsEnumConverter}}"
Style="{StaticResource flagsComboBox}"
/>
And resources (which explain usage of value converters):
<Application.Resources>
<Style x:Key="enumComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding Path=.,Mode=OneWay, Converter={local:LocalizedEnumConverter}}" Style="{x:Null}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="flagsComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding Path=Checked,Mode=TwoWay}"/>
<TextBlock Text="{Binding Path=Name,Mode=OneWay}"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
I use a custom Checkbox to do so. It works perfectly and simply. See comments on top of the class to know how to use it.
Hope it helps...
using System;
using System.Windows;
using System.Windows.Controls;
namespace HQ.Wpf.Util.MyControl
{
/// <summary>
/// Usage: Bind EnumFlag and Two way binding on EnumValue instead of IsChecked
/// Example: <myControl:CheckBoxForEnumWithFlagAttribute
/// EnumValue="{Binding SimulationNatureTypeToCreateStatsCacheAtEndOfSimulation, Mode=TwoWay}"
/// EnumFlag="{x:Static Core:SimulationNatureType.LoadFlow }">Load Flow results</myControl:CheckBoxForEnumWithFlagAttribute>
/// </summary>
public class CheckBoxForEnumWithFlagAttribute : CheckBox
{
// ************************************************************************
public static DependencyProperty EnumValueProperty =
DependencyProperty.Register("EnumValue", typeof(object), typeof(CheckBoxForEnumWithFlagAttribute), new PropertyMetadata(EnumValueChangedCallback));
public static DependencyProperty EnumFlagProperty =
DependencyProperty.Register("EnumFlag", typeof(object), typeof(CheckBoxForEnumWithFlagAttribute), new PropertyMetadata(EnumFlagChangedCallback));
// ************************************************************************
public CheckBoxForEnumWithFlagAttribute()
{
base.Checked += CheckBoxForEnumWithFlag_Checked;
base.Unchecked += CheckBoxForEnumWithFlag_Unchecked;
}
// ************************************************************************
private static void EnumValueChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var checkBoxForEnumWithFlag = dependencyObject as CheckBoxForEnumWithFlagAttribute;
if (checkBoxForEnumWithFlag != null)
{
checkBoxForEnumWithFlag.RefreshCheckBoxState();
}
}
// ************************************************************************
private static void EnumFlagChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
var checkBoxForEnumWithFlag = dependencyObject as CheckBoxForEnumWithFlagAttribute;
if (checkBoxForEnumWithFlag != null)
{
checkBoxForEnumWithFlag.RefreshCheckBoxState();
}
}
// ************************************************************************
public object EnumValue
{
get { return GetValue(EnumValueProperty); }
set { SetValue(EnumValueProperty, value); }
}
// ************************************************************************
public object EnumFlag
{
get { return GetValue(EnumFlagProperty); }
set { SetValue(EnumFlagProperty, value); }
}
// ************************************************************************
private void RefreshCheckBoxState()
{
if (EnumValue != null)
{
if (EnumValue is Enum)
{
Type underlyingType = Enum.GetUnderlyingType(EnumValue.GetType());
dynamic valueAsInt = Convert.ChangeType(EnumValue, underlyingType);
dynamic flagAsInt = Convert.ChangeType(EnumFlag, underlyingType);
base.IsChecked = ((valueAsInt & flagAsInt) > 0);
}
}
}
// ************************************************************************
private void CheckBoxForEnumWithFlag_Checked(object sender, RoutedEventArgs e)
{
RefreshEnumValue();
}
// ************************************************************************
void CheckBoxForEnumWithFlag_Unchecked(object sender, RoutedEventArgs e)
{
RefreshEnumValue();
}
// ************************************************************************
private void RefreshEnumValue()
{
if (EnumValue != null)
{
if (EnumValue is Enum)
{
Type underlyingType = Enum.GetUnderlyingType(EnumValue.GetType());
dynamic valueAsInt = Convert.ChangeType(EnumValue, underlyingType);
dynamic flagAsInt = Convert.ChangeType(EnumFlag, underlyingType);
dynamic newValueAsInt = valueAsInt;
if (base.IsChecked == true)
{
newValueAsInt = valueAsInt | flagAsInt;
}
else
{
newValueAsInt = valueAsInt & ~flagAsInt;
}
if (newValueAsInt != valueAsInt)
{
object o = Enum.ToObject(EnumValue.GetType(), newValueAsInt);
EnumValue = o;
}
}
}
}
// ************************************************************************
}
}
In WPF, is it possible to bind the key in "{StaticResource key}"to a variable.
For example. I have a variable ExecutionState with the states Active and Completed.
In my ResourceDictionary I have
<Style TargetType="{x:Type TextBlock}" x:Key="Active">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="Completed">
<Setter Property="Foreground" Value="Green"/>
</Style>
Instead of having
<TextBlock Style="{StaticResource Active}"/>
I Would like to have something like
<TextBlock Style="{StaticResource {Binding ExecutionState}}"/>
Thus if the state changes the text color changes.
Is something like this even possible?
I can achieve the wanted functionality using triggers, but I have to reuse it at several places and I don't want to clutter my code.
I am using MVVM also.
thanx
No, it's not possible. Binding can only be set on a DependencyProperty. StaticResource is not a DependencyObject, so there is no DependencyProperty. You should use Trigger(s) or develop your own attached behavior.
There is no direct way to achieve .
Create one attached property and assign the property name to bind.
In the property change callback function update control style.
<TextBlock dep:CustomStyle.StyleName="{Binding ExecutionState}" Text="Thiru" />
public static class CustomStyle
{
static FrameworkPropertyMetadata _styleMetadata = new FrameworkPropertyMetadata(
string.Empty, FrameworkPropertyMetadataOptions.AffectsRender, StyleNamePropertyChangeCallBack);
public static readonly DependencyProperty StyleNameProperty =
DependencyProperty.RegisterAttached("StyleName", typeof (String), typeof (CustomStyle), _styleMetadata);
public static void SetStyleName(UIElement element, string value)
{
element.SetValue(StyleNameProperty, value);
}
public static Boolean GetStyleName(UIElement element)
{
return (Boolean)element.GetValue(StyleNameProperty);
}
public static void StyleNamePropertyChangeCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FrameworkElement ctrl = d as FrameworkElement;
if (ctrl.IsLoaded)
{
string styleName = Convert.ToString(e.NewValue);
if (!string.IsNullOrEmpty(styleName))
{
ctrl.Style = ctrl.TryFindResource(styleName) as Style;
}
}
}
}
I have defined the following DataTemplate for ListBox items in an external resource dictionary:
<DataTemplate x:Key="MyListBoxItemTemplate" DataType="{x:Type entities:Track}">
<StackPanel>
<TextBlock Text="Here's the slider:" />
<Slider Name="MySlider" Height="23" Minimum="0" />
</StackPanel>
</DataTemplate>
I need to provide an event handler method for Slider's ValueChanged event. I don't know where am I supposed to write that code as it is impractical to specify event handler for a control within a template.
I've been googling for the solution and found that I should add the event handler in the override of the OnApplyTemplate() method. My guess is that it should look something like this or similar:
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Is the following initialization even going to work!?!?
Slider MySlider = this.FindName("MySlider") as Slider;
SeekSlider.ValueChanged +=
new RoutedPropertyChangedEventHandler<double>(SeekSlider_ValueChanged);
}
But where should I write this method? Does OnApplyTemplate overriding only applies to ControlTemplates or is my scenario included as well? Should I provide ControlTemplate instead of DataTemplate? Is the body of the method I have provided correct?
Please help. Thanks.
Using the OnApplyTemplate approach will work if you if you're working with the ControlTemplate for a Control. For example, if you've subclassed TextBox you could do this like
public class MyTextBox : TextBox
{
public override void OnApplyTemplate()
{
MySlider MySlider = GetTemplateChild("MySlider") as MySlider;
if (MySlider != null)
{
MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
}
base.OnApplyTemplate();
}
void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
//...
}
}
I don't think this approach will work in your situation however. You could use the Loaded event for ListBoxItem and find the Slider in the visual tree in the event handler
<ListBox ...>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="Loaded" Handler="ListBoxItem_Loaded"/>
</Style>
</ListBox.ItemContainerStyle>
<!--...-->
</ListBox>
Code behind
private void ListBoxItem_Loaded(object sender, RoutedEventArgs e)
{
ListBoxItem listBoxItem = sender as ListBoxItem;
Slider MySlider = GetVisualChild<Slider>(listBoxItem);
MySlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(MySlider_ValueChanged);
}
void MySlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
}
GetVisualChild
private static T GetVisualChild<T>(DependencyObject parent) where T : Visual
{
T child = default(T);
int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
{
child = GetVisualChild<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}
Little know fact is that ResourceDictionaries can hold CodeBehind as well..
As a general rule of thumb I don't think that putting DataTemplates in ResourceDictionaries is a good idea to begin with (your question being an example for one of the reasons), this is how you can solve it:
XAML:
<ResourceDictionary
x:Class="WpfApplication24.Dictionary1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="MyDataTemplate">
<StackPanel>
<TextBlock Text="Hello" />
<Slider ValueChanged="ValueChanged"/>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
and code behind:
namespace WpfApplication24
{
public partial class Dictionary1 : ResourceDictionary
{
public void ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Debug.Write("Hello");
}
}
}
Anyhow, as Meleak said above me - OnApplyTemplate is only relevant for Control Templates and not Data Templates.
Have a look at this question and answer.
I think that using Commands is the best option.
EDIT A good tutorial
You can use EventSetter in the style you are setting the template with:
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="MouseWheel" Handler="GroupListBox_MouseWheel" />
<Setter Property="Template" ... />
</Style>
Method 1:
Use your own control inherited from Slider:
public class SpecialSlider : Slider
{
public SpecialSlider()
{
ValueChanged += OnValueChanged;
}
private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// ...
}
}
Method 2: use behaviors from System.Windows.Interactivity.dll assembly (available through the NuGet):
public class SpecialSliderBehavior : Behavior<Slider>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.ValueChanged += OnValueChanged;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.ValueChanged -= OnValueChanged;
}
private void OnValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
// ...
}
}
This is how to attach it:
...
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
...
<DataTemplate x:Key="MyListBoxItemTemplate" DataType="{x:Type entities:Track}">
<Slider Name="MySlider">
<i:Interaction.Behaviors>
<SpecialSliderBehavior />
</i:Interaction.Behaviors>
</Slider>
</DataTemplate>
I want to copy the content of one text box to another text box by clicking the mouse.
How do I bind a mouse click event?
This sample is for RightClick, but you can adjust the event according to your needs:
<TextBox>
<TextBox.InputBindings>
<MouseBinding Gesture="RightClick" Command="{Binding YourCommand}" />
</TextBox.InputBindings>
</TextBox>
Edit: I uploaded on my SkyDrive a sample app that illustrates how to use this method in order to achieve exactly what you need. Please be advised that it will only work for .NET Framework 4+
Want to add a behavior to a control ? Just use the Ramora pattern !
Hope this helps
Use this code for TreeView
<TreeView commandBehaviors:MouseDoubleClick.Command="{Binding YourCommand}"
commandBehaviors:MouseDoubleClick.CommandParameter="{Binding}"
.../>
Use this code for TreeViewItem
<TreeView ItemsSource="{Binding Projects}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command"
Value="{Binding YourCommand}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter"
Value="{Binding}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
Use this code to create a new behavior MouseDoubleClick
public class MouseDoubleClick
{
public static DependencyProperty CommandProperty =
DependencyProperty.RegisterAttached("Command",
typeof(ICommand),
typeof(MouseDoubleClick),
new UIPropertyMetadata(CommandChanged));
public static DependencyProperty CommandParameterProperty =
DependencyProperty.RegisterAttached("CommandParameter",
typeof(object),
typeof(MouseDoubleClick),
new UIPropertyMetadata(null));
public static void SetCommand(DependencyObject target, ICommand value)
{
target.SetValue(CommandProperty, value);
}
public static void SetCommandParameter(DependencyObject target, object value)
{
target.SetValue(CommandParameterProperty, value);
}
public static object GetCommandParameter(DependencyObject target)
{
return target.GetValue(CommandParameterProperty);
}
private static void CommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
Control control = target as Control;
if (control != null)
{
if ((e.NewValue != null) && (e.OldValue == null))
{
control.MouseDoubleClick += OnMouseDoubleClick;
}
else if ((e.NewValue == null) && (e.OldValue != null))
{
control.MouseDoubleClick -= OnMouseDoubleClick;
}
}
}
private static void OnMouseDoubleClick(object sender, RoutedEventArgs e)
{
Control control = sender as Control;
ICommand command = (ICommand)control.GetValue(CommandProperty);
object commandParameter = control.GetValue(CommandParameterProperty);
command.Execute(commandParameter);
}
}
It sounds like you are inventing a new behaviour for your textbox :)
I would just consider if the users of your program understands and likes this behaviour.
Maybe it is easier to understand the funcionality if it is just a button you have to click - it is also faster to implement :)
I think you could bind mouse gestures to commands. Take a look at this: http://www.thejoyofcode.com/Invoking_a_Command_on_a_Double_Click_or_other_Mouse_Gesture.aspx
I'm not sure what exactly you're wanting to bind to.
There is no readily available MouseClick event as far as i'm aware.
the Click event as you'd find on a Button is inherited from ButtonBase and is not readily available on most controls.
MouseDoubleClick is inherited from Control and available on anythning deriving from it.
in your example it sounds like a simple Button with its Click event handled might do the trick.
To bind to the click event, you just need to specify the event handler for the event in the Button.
Something like:
XAML:
<TextBox Name=TextBoxOne />
<TextBox Name=TextBoxTwo />
<Button Click="CopyTextButton_Click"/>
And in your code behind:
void CopyTextButton_Click(object sender, RoutedEventArgs e)
{
//Copy the text and anything else you need done
}
Otherwise if this is a more specialised scenario, you might want to investigate using a UserControl or as AndrewS answered above, a Command.
Hope it helps.
You can easily do this by creating a new behavior.
<TextBox
MouseDoubleClick="SelectAddress"
GotKeyboardFocus="SelectAddress"
PreviewMouseLeftButtonDown="SelectivelyIgnoreMouseButton" />
Here's the code behind:
private void SelectAddress(object sender, RoutedEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
tb.SelectAll();
}
}
private void SelectivelyIgnoreMouseButton(object sender,
MouseButtonEventArgs e)
{
TextBox tb = (sender as TextBox);
if (tb != null)
{
if (!tb.IsKeyboardFocusWithin)
{
e.Handled = true;
tb.Focus();
}
}
}
Please update this snippet according to your need.