WPF UserControl Child Component Event Handler - c#

I have a UserControl that contain let's say a button (or any other object).
<UserControl x:Class="StackOverFlowQuestion.UserControlButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:StackOverFlowQuestion"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Button
x:Name="Button1"
Content="Click me for testing"/>
</Grid>
</UserControl>
and I want to access that Button's(Or any Object) Click Event or any Event form the parent that contains the UserControl.
<Window x:Class="StackOverFlowQuestion.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StackOverFlowQuestion"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControlButton/>
</Grid>
</Window>
Thanks.

It's quite easy. Just put a public event to the UserControl (code behind) for it could be accessible from outside of UserControl and do forward the Click event from your button.
public partial class UserControlButton : UserControl
{
public event RoutedEventHandler ButtonClick;
private void UsrCtlButton_Click(object sender, RoutedEventArgs e)
{
ButtonClick?.Invoke(sender, e);
}
}
XAML of UserControl:
<Button x:Name="Button1" Content="Click me for testing" Click="UsrCtlButton_Click"/>
XAML where UserControl being used:
<local:UserControlButton ButtonClick="Some_event_handler_to_handle_Button_Click"/>

Related

WPF MVVM - How can I pass two variables from the ViewModel associated with the first window to the second ViewModel associated with the second window?

I don't want to use Prism or MVVM Light solutions and would like to pass two parameters to the second window? How could I do that? I was looking for some information on this topic, but unfortunately most of them use packages...
try this:
App.xaml
<Application.Resources>
<vm:MainViewModel x:Key="YourViewModel" />
</Application.Resources>
MainWindow.xaml
<Window x:Class="ABC.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ABC"
DataContext="{StaticResource YourViewModel}"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding SomeVar}"/>
</Grid>
</Window>
SecondWindow.xaml
<Window x:Class="ABC.SecondWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ABC"
DataContext="{StaticResource YourViewModel}"
mc:Ignorable="d"
Title="SecondWindow" Height="450" Width="800">
<Grid>
<TextBox Text="{Binding SomeVar}"/>
</Grid>
</Window>
I guess you could just send parameters in the constructor of the second window, wherever you are creating your window.
var newwin = new SecondWindow("second param is int", 42 );
newwin.Show();
And then just create an another constructor for your window:
public SecondWindow(string a, int b) : this()
{
var secondVM = (SecondViewModel)DataContext;
secondVM.IAmSendingYouTwoParams( a,b);
...
}

Can't bind ViewModelLocator

I made a class for store ViewModels
internal class Locator
{
public MainViewModel MainViewModel { get; } = new MainViewModel();
}
And added it to application resources
<Application x:Class="Marathon.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Marathon"
StartupUri="MainWindow.xaml">
<Application.Resources>
<local:Locator x:Key="Locator" x:Name="Locator"/>
</Application.Resources>
</Application>
Then bound it Locator to the Main Window
<Window x:Class="App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"
Title="MainWindow" MinHeight="350" MinWidth="525">
<Grid>
<Frame Content="{Binding Page}"></Frame>
</Grid>
</Window>
It works.
When I add a binding (DataContext) to a Page. It throws an exception (System.Windows.Markup.XamlParseException, Cannot find resource named 'Locator'.).
<Page x:Class="App.Pages.StartPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"
Title="StartPage">
<Grid>
</Grid>
</Page>
How to bind DataContext to a page?
You don't need x:Name in your App.xaml declaration of the locator instance, x:Key is sufficient
The error most occurs if and when you instantiate the Page itself in the view model.
A view model shouldn't create Page objects. Try to return a Uri instead and bind to the Source property instead:
<Window x:Class="App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding Source={StaticResource Locator}, Path=MainViewModel}"
Title="MainWindow" MinHeight="350" MinWidth="525">
<Grid>
<Frame Source="{Binding Page}" />
</Grid>
</Window>
This should work:
public class MainViewModel
{
public Uri Page { get; } = new Uri("Page1.xaml", UriKind.RelativeOrAbsolute);
}

Binding to child properties from parent control

I have an user control:
<UserControl x:Class="WpfApplication2.Control1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<StackPanel Orientation="Horizontal" Name="StackPanelInsideUserControl">
<Label />
<TextBox Name="TextBoxInsideUserControl" Text="Initial Text" />
<Button Content="OK" />
</StackPanel>
</Grid>
And I'm trying to bind to the Text property of the TextBoxInsideUserControl TextBox from a its parent like in:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:Control1 StackPanelInsideUserControl.TextBoxInsideUserControl.Text="{Binding SomeText}" />
</Grid>
How can I achieve that? Does xaml allow us to do that?
As requested, the comment as answer:
No, not really. You should define a dependency property on that UserControl, bind that to the Text of the TextBox. Then you can access the text outside of the UserControl via that dependency property.

UserControl in windows phone 8.1 blank template

My requirement is masterpage in windows phone 8.1 blank template, i searched in the google, they suggest the usercontrol, i applied that scenario but not working,Below is my tried sample code.
`I'm try create Application where i required to use User Control.I'm already created MainPage.xaml here code below
`
<Page
x:Class="VtDesigning.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VtDesigning"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
</Grid>
</Page>
and usercontrol defined below
<UserControl
x:Class="VtDesigning.MyUserControl2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VtDesigning"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid>
<StackPanel Height="50" Background="Chocolate">
<TextBlock Text="hi hellow how are you"
FontSize="25"
Margin="0,0,154,0"/>
</StackPanel>
</Grid>
</UserControl>
How to i call this usercontrol in MainPage.xaml.
Thanks,
Venky.
Set a reference to the location of the user control and add the user control to your layout as a normal control
<Page
x:Class="VtDesigning.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:VtDesigning"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:project="using:MyProject.UserControls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<project:MyUserControl/>
</Grid>

WPF Mouse Down Event won't fire

I must be doing something stupid here but I cant get a MouseDown event to fire when I am clicking on the UserControl. Driving me Mad.
Here's the XAML for the UserControl:
<UserControl x:Name="cusTextBox" x:Class="StoryboardTool.CustomTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" MouseDown="cusTextBoxControl_MouseDown">
<Grid>
<RichTextBox x:Name="richTextBox">
<RichTextBox.ContextMenu>
<ContextMenu>
<MenuItem x:Name="ContextMenuBringForward" Header="BringForward" Click="ContextMenuBringForward_Click"/>
<MenuItem x:Name="ContextMenuSendBackward" Header="SendBackward" Click="ContextMenuSendBackward_Click"/>
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
</Grid>
</UserControl>
Code Behind:
private void cusTextBoxControl_MouseDown(object sender, MouseButtonEventArgs e)
{
selected = (CustomTextBox)sender;
}
Why wont this fire when I am clicking the User Control?
You MouseDown is handled by RichTextBox. Use PreviewMouseDown instead.

Categories