I have a UWP application:
My app command bar (XAML 2) manages TabView content (XAML 1). I need different command bars for different tab types. Now I using several frames in second XAML, and I can't change it from XAML 1.
How I can change XAML 2 UI from XAML 1 .cs file?
Thanks for any help.
UPD:
I have main XAML:
<Page
x:Class="Test.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NetChrom"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="BaseGrid">
<Grid.RowDefinitions>
<!-- titlebar -->
<RowDefinition x:Name="Titlebar" Height="30">
</RowDefinition>
<!-- toolbar -->
<RowDefinition x:Name="Toolbar" Height="110">
</RowDefinition>
<!-- main window -->
<RowDefinition>
</RowDefinition>
</Grid.RowDefinitions>
<Grid x:Name="TitlebarGrid" Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="5*">
</ColumnDefinition>
</Grid.ColumnDefinitions>
<local:TitleBar/>
</Grid>
<Grid x:Name="ToolbarGrid" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="37*">
</ColumnDefinition>
<ColumnDefinition Width="27*"/>
</Grid.ColumnDefinitions>
<!-- toolbar -->
<local:Toolbar Grid.ColumnSpan="2"/>
</Grid>
<!-- content-->
<Grid x:Name="MainContent" Grid.Row="2" Background="AliceBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition MaxWidth="325" MinWidth="120">
</ColumnDefinition>
<ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" Background="#F3F3F3">
<local:MainTabbar/>
</Grid>
<Grid Grid.Column="0" Background="LightBlue">
<local:FileManager/>
</Grid>
<controls:GridSplitter
Margin="0,10,10,0"
Opacity="0"
Background="Transparent"
GripperCursor="Default"
HorizontalAlignment="Left"
Grid.Column="1"
ResizeDirection="Auto"
ResizeBehavior="BasedOnAlignment"
CursorBehavior="ChangeOnSplitterHover"
Width="0">
<controls:GridSplitter.RenderTransform>
<TranslateTransform X="-8" />
</controls:GridSplitter.RenderTransform>
</controls:GridSplitter>
</Grid>
</Grid>
</Page>
and in this XAML there are two another XAML: MainTabbar (XAML 1) and Toolbar (XAML 2) from scheme.
This is Toolbar.xaml:
<UserControl
x:Class="Test.Toolbar"
x:Name="toolbarControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:local="using:Test"
xmlns:met="using:Test.Method"
xmlns:chr="using:Test.ChrOptions"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DesignHeight="110"
d:DesignWidth="1920">
<Border CornerRadius="0,0,10,10" BorderBrush="#D4D4D4" BorderThickness="1,0,1,1" Background="#F3F3F3">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="110">
</RowDefinition>
</Grid.RowDefinitions>
<Grid x:Name="MainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition>
</ColumnDefinition>
<ColumnDefinition Width="320"/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
</StackPanel>
</Grid>
<Grid Grid.Column="0">
<Frame x:Name="toolbarFrame"/> <!-- cmdbar frame>
</Grid>
</Grid>
</Grid>
</Border>
</UserControl>
This is MainTabbar:
<Page
x:Class="Test.MainTabbar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Test"
xmlns:met="using:Test.Method"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DesignWidth="1595">
<Grid Margin="10,0,0,0">
<muxc:TabView x:Name="Tabs"
IsAddTabButtonVisible="False"
VerticalAlignment="Stretch"
TabCloseRequested="Tabs_TabCloseRequested"
AllowDropTabs="True"
CanDragTabs="False"
CanReorderTabs="True"
TabDroppedOutside="Tabs_TabDroppedOutside"
TabStripDragOver="Tabs_TabStripDragOver"
TabStripDrop="Tabs_TabStripDrop"
TabDragStarting="Tabs_TabDragStarting" >
<muxc:TabView.TabItems>
<muxc:TabViewItem Header="SampleMethod.met" IsClosable="False">
<muxc:TabViewItem.IconSource>
<muxc:SymbolIconSource Symbol="Placeholder" />
</muxc:TabViewItem.IconSource>
<!-- <Frame x:Name="MethodFrame"/> -->
<met:MethodTabView/>
</muxc:TabViewItem>
<muxc:TabViewItem Header="SampleChrome.chr" IsClosable="False">
<muxc:TabViewItem.IconSource>
<muxc:SymbolIconSource Symbol="Placeholder" />
</muxc:TabViewItem.IconSource>
<local:ChrView/>
</muxc:TabViewItem>
</muxc:TabView.TabItems>
<muxc:TabView.TabStripHeader>
<Grid x:Name="ShellTitlebarInset" Background="#F3F3F3" />
</muxc:TabView.TabStripHeader>
<muxc:TabView.TabStripFooter>
<Grid x:Name="CustomDragRegion" Background="#F3F3F3" />
</muxc:TabView.TabStripFooter>
</muxc:TabView>
</Grid>
</Page>
I need to get current tab type in MainTabbar.xaml.cs (it's ok). And then change Command Bar in Toolbar.xaml frame.
I wrote this procedure for change frame in Toolbar.xaml.cs:
public void setMetCmdbarMode()
{
toolbarFrame.Navigate(typeof(MethodToolbar), null);
}
But I don't know how I can call this function from MainTabbar class, or how I can translate tab type to Toolbar class.
After checking your code, you could try to create a custom event in the MainTabbar, and handle it in the MainPage. This event is triggered when the selected item of the TabView is changed. Then you could get notified in the MainPage and call method to change the Toolbar.
Here are the detailed steps:
Create a custom Event named TabItemChanged on the MainTabbar page and call it in the TabView_SelectionChanged event.
Handle the TabItemChanged in the MainPage
Change the content of the Toolbar as you want in the EventHandler based on the TabViewItem.
Code in MainTabbar:
public sealed partial class MainTabbar : Page
{
public event EventHandler TabItemChanged;
public MainTabbar()
{
this.InitializeComponent();
}
private void Tabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this.TabItemChanged != null)
this.TabItemChanged(Tabs.SelectedItem, new EventArgs());
}
}
In the MainPage.Xaml
<local:MainTabbar TabItemChanged="MainTabbar_TabItemChanged"/>
In the MainPage.Xaml.cs
private void MainTabbar_TabItemChanged(object sender, EventArgs e)
{
MUXC.TabViewItem tabitem = sender as MUXC.TabViewItem;
switch (tabitem.Tag)
{
case "123":
Debug.WriteLine("FirstItemSelectecd");
//call method for toobar to change content
//like setMetCmdbarMode()
break;
case "234":
Debug.WriteLine("SecondItemSelectecd");
//call method for toobar to change content
//like setMetCmdbarMode()
break;
}
}
Update:
Give the toolbar a name in MainPage.Xaml
<local:Toolbar x:Name="myToolbar" Grid.ColumnSpan="2"/>
Then call it in the MainPage.Xam.cs:
switch (tabitem.Tag)
{
case "123":
Debug.WriteLine("FirstItemSelectecd");
myToolbar.setMetCmdbarMode();
break;
case "234":
Debug.WriteLine("SecondItemSelectecd");
break;
}
Related
I have a window that expands to left and to the right.
Simplified example:
<Window x:Class="Application1.Windows.Test"
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"
Title="MainWindow"
SizeToContent="Width" Height="250">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <!--Expander LEFT-->
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="175" /> <!--Red Content -->
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="Auto"/> <!--Expander RIGHT-->
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="*"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Expander Grid.Column="0"
Grid.Row="0"
Grid.RowSpan="3"
Margin="5"
ExpandDirection="Left">
<Grid Width="200">
</Grid>
</Expander>
<Grid Grid.Column="2"
Grid.RowSpan="3"
Background="Red"/>
<Expander Grid.Column="4"
Grid.Row="0"
Grid.RowSpan="3"
Margin="5"
ExpandDirection="Right">
<Grid Width="200">
</Grid>
</Expander>
</Grid>
Here you can see what the problem is:
I've already had a look on WPF - Expand Window to the Left.
The solution kind of works but that is only solving half of the problem.
How to do that for Left AND Right ?
UPDATE
I do not want the Expander columns to be fixed. They should just show the minimal space needed for the expander
One approach that will work is this:
(But I'm somehow unsatisfied with this solution)
Create an Enum to store the last Action in:
public enum ExpandActions
{
ExpandRight,
ExpandLeft,
CollapsRight,
CollapseLeft
}
Then I added the handlers for Expand & Collapse to my Expanders in xaml.
At last override SizeChanged on the Window as in WPF - Expand Window to the Left.
We only want this behavior, when expanding to left - otherwise we would kill our 'expand-to-right' behavior.
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
if (!sizeInfo.WidthChanged)
{
base.OnRenderSizeChanged(sizeInfo);
return;
}
Hide();
base.OnRenderSizeChanged(sizeInfo);
//Last action was on left expander
if(_lastAction == ExpandActions.CollapseLeft || _lastAction == ExpandActions.ExpandLeft)
{
Left -= (sizeInfo.NewSize.Width - sizeInfo.PreviousSize.Width);
}
Show();
}
Good point about this is that expansion out of screen could be handled.
It works but I guess it's not the best solution.
The result is this:
I have created a User Control that is designed to simplify the use of a recursive popup dialog system in which a popup dialog can have a popup dialog open within it.
Here is the User Control's XAML:
<UserControl x:Class="SEA.WPF.View.Controls.DialogPresenter"
Name="This"
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:SEA.WPF.View.Controls"
xmlns:ts="clr-namespace:SEA.WPF.View.TemplateSelectors"
xmlns:c="clr-namespace:SEA.WPF.View.DataConverters"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<c:InstanceToVisibilityConverter x:Key="InstanceToVisibilityConverter" />
</ResourceDictionary>
</UserControl.Resources>
<Grid Visibility="{Binding Dialog, Converter={StaticResource InstanceToVisibilityConverter}}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Grid.Row="1" Grid.Column="1">
<ContentControl Content="{Binding Path=Dialog, ElementName=This}"
ContentTemplateSelector="{Binding Path=DialogTemplateSelector, ElementName=This}" />
</Border>
<ContentControl Grid.RowSpan="3" Grid.ColumnSpan="3" Content="{Binding Path=Dialog.Dialog, ElementName=This}">
<ContentControl.ContentTemplateSelector>
<ts:InstanceOnlyTemplateSelector>
<ts:InstanceOnlyTemplateSelector.Template>
<DataTemplate>
<local:DialogPresenter Dialog="{Binding Path=Dialog.Dialog, ElementName=This}"
DialogTemplateSelector="{Binding Path=DialogTemplateSelector, ElementName=This}" />
</DataTemplate>
</ts:InstanceOnlyTemplateSelector.Template>
</ts:InstanceOnlyTemplateSelector>
</ContentControl.ContentTemplateSelector>
</ContentControl>
</Grid>
</UserControl>
Here is InstanceOnlyTemplateSelector:
using System.Windows;
using System.Windows.Controls;
namespace SEA.WPF.View.TemplateSelectors
{
public class InstanceOnlyTemplateSelector : DataTemplateSelector
{
public DataTemplate Template
{
get;
set;
}
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return item == null ? null : Template;
}
}
}
The InstaceOnlyTemplateSelector is there so that the recursive DialogPresenter is only rendered when the child dialog is not null (thus avoiding a Stack Overflow cause by the recursive binding).
The problem is, that when the child dialog changes from null to something else then the recursive DialogPresenter does not render like it's parent. I have tried replacing the DialogPresenter with a Grid with Background equal to Brushes.Black and that made the whole screen black (as expected).
Why is the recursive instance of the DialogPresenter not rendering as expected?
Problem
I needed to make controls that used images as backgrounds that could be any width without distorting the images. For example if I used a single image and stretched it the rounded corners of the image would become distorted.
Solution
The solution, given by Noxivs, was to use a custom UserControl with three images, two sides and a middle that is stretched.
It is important to add SnapsToDevicePixels="True" to the UserControl Grid as without that a single pixel gap appeared between the images.
MainWindow.xaml
<Window x:Class="Testing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ns="clr-namespace:Testing"
Title="MainWindow" Height="350" Width="525">
<Grid Name="MainGrid">
<ns:ScalableTextBox TextBoxText="Added in XAML" Width="120" Margin="0,0,0,100">
</ns:ScalableTextBox>
</Grid>
</Window>
MainWindow.xaml.cs
ScalableTextBox scalableTextBox = new ScalableTextBox();
scalableTextBox.TextBoxText = "Added in C#";
scalableTextBox.Width = 100;
MainGrid.Children.Add(scalableTextBox);
ScalableTextBox.xaml.cs
public partial class ScalableTextBox : UserControl
{
public ScalableTextBox()
{
InitializeComponent();
}
public string TextBoxText
{
get { return this.TextBoxName.Text; }
set { this.TextBoxName.Text = value; }
}
}
ScalableTextBox.xaml
<UserControl x:Class="Testing.ScalableTextBox"
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="36" d:DesignWidth="50" Height="36" MinWidth="29">
<Grid>
<Grid SnapsToDevicePixels="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="pack://siteoforigin:,,,/Images/left.png" />
<Image Grid.Column="1" Stretch="Fill" Source="pack://siteoforigin:,,,/Images/center.png"/>
<Image Grid.Column="2" Source="pack://siteoforigin:,,,/Images/right.png" />
</Grid>
<TextBox Name="TextBoxName" VerticalAlignment="Center"
HorizontalAlignment="Center" Background="{x:Null}"
BorderBrush="{x:Null}" FontSize="12"/>
</Grid>
</UserControl>
Thanks again to Noxivs!
I'm not sure to understand what you want but :
I think you can create exactly the same design of your images in XAML
(vectorial keeps your style no matter the size).
What about the creation of your own control user with your textbox (0
opacity) and as many images as you want in the background ? (not really nice)
These are only suggestions.
EDIT :
And here is your scalable textbox :
I had to split your first image.
http://i.stack.imgur.com/cGJ8u.png
http://i.stack.imgur.com/Fo4Oo.png
<UserControl x:Class="YourNamespace.ScalableTextBox"
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" Height="36" MinWidth="29">
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="left.png" />
<Image Grid.Column="1" Source="center.png" Stretch="Fill"/>
<Image Grid.Column="2" Source="right.png" />
</Grid>
<TextBox VerticalAlignment="Center" Background="{x:Null}" BorderBrush="{x:Null}" FontSize="14" FontFamily="Comic Sans MS" Margin="8,0"/>
</Grid>
<Window x:Class="YourNamespace.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ns="clr-namespace:_28400241"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ns:ScalableTextBox></ns:ScalableTextBox>
</Grid>
</Window>
I still think it is better to create the controls in XAML.
Regards.
EDIT 2 :
With a dynamic loading of images (myGrid is the main grid of the window, and i named the 3 images control in the ScalableTextBox object) :
public MainWindow()
{
InitializeComponent();
ScalableTextBox tb = new ScalableTextBox();
tb.Width = 140;
BitmapImage src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri("./left.png", UriKind.Relative);
src.EndInit();
tb.LeftImage.Source = src;
src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri("./center.png", UriKind.Relative);
src.EndInit();
tb.CenterImage.Source = src;
src = new BitmapImage();
src.BeginInit();
src.UriSource = new Uri("./right.png", UriKind.Relative);
src.EndInit();
tb.RightImage.Source = src;
Grid.SetRow(tb, 0);
Grid.SetColumn(tb, 0);
myGrid.Children.Add(tb);
}
I'm not sure to understand what you want but if you just want the image to appear as a background for the textbox, you could create a style for the textbox, modify the ControlTemplate and place a grid within it, containing the images.
For example (this is just to give you an idea of what I am trying to explain, not the exact code to implement):
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="14" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="14" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="left.png" />
<Image Grid.Column="1" Source="center.png" Stretch="Fill"/>
<Image Grid.Column="2" Source="right.png" />
<ScrollViewer x:Name="ContentElement" Grid.Column="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
First, let me show you how my code is cut.
I have this code in a xaml UC (eventsUC.xaml) :
<UserControl x:Class="QuimeO.UserControls.Lists.EventsListUC"
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:ToggleSwitch="clr-namespace:ToggleSwitch;assembly=ToggleSwitch"
mc:Ignorable="d"
Width="477"
>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" Width="auto" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ItemsControl Grid.Row="0" BorderThickness="0" x:Name="eventsList" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ItemsControl.Resources>
<ResourceDictionary x:Name="eventslisttempplate" Source="EventsListTemplate.xaml" />
</ItemsControl.Resources>
</ItemsControl>
</ScrollViewer>...
My EventsListTemplate.xaml looks like this :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="QuimeO.UserControls.Lists.EventsListTemplate"
xmlns:apiNamespace="clr-namespace:QuimeO.DBO"
>
<DataTemplate DataType="{x:Type apiNamespace:EventsDictionary}">
<StackPanel Orientation="Vertical">
<Border BorderBrush="LightGray" BorderThickness="0,0,0,1" Margin="0,5,0,0">
<TextBlock HorizontalAlignment="Right" Foreground="Gray" Text="{Binding FormatedDate}" FontSize="14"></TextBlock>
</Border>
<ListView Grid.Row="0" x:Name="eventsList" ItemsSource="{Binding Events}" BorderThickness="0" MouseDoubleClick="eventsList_MouseDoubleClick">
</ListView>
</StackPanel>
</DataTemplate>
</ResourceDictionary>
And my EventsListTemplate.xaml.cs code behind looks like this
public partial class EventsListTemplate : ResourceDictionary
{
public Delegate MainWindowControlPointer;
private void eventsList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var ev = ((sender as ListView).SelectedItem as ListViewItem).DataContext as Event;
System.Diagnostics.Debug.WriteLine(ev.Name);
this.MainWindowControlPointer.DynamicInvoke(ev.Ancestors.Root, new Element() { Category = ev.Category, Id = ev.Id, Name = ev.Name });
}
}
When I click on an item of my listview in my template, it trigger the eventsList_MouseDoubleCkick and I can retrieve my event.
However, I would like to trigger an action in the UC where the template is created (first source code block).
To do that, I just want to create a delegate in my Template (technicaly, in a perfect world, something like "this.rd_eventslisttemplate.MainWindowControlPointer = ... "). But, I don't know how to do it or if this is even possible.
After encrypting your question for a while I think I got it.
There is a nice method called VisualTreeHelper.GetParent() which gets you the parent of a control in VisualTree.
Now to your problem when you catch your event in EventsListTemplate you will need to call GetParent() few times till you finally get the instance of your UserControl.
Thats it.
I have the following main.xaml and usercontrol.
I need to place several times the user control on the 2nd row, 2nd column of the grid, By using visual studio it wont allow to drag and drop the user control, so I suppose I have to do it by code, I just dont know how
MainPage.xaml
<Grid HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="1366" x:Name="grid" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="150"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Border BorderBrush="White" BorderThickness="3" Grid.Column="1" Background="Red" CornerRadius="30"/>
<TextBlock x:Name="txtCountry" Grid.Column="1" TextWrapping="Wrap" FontSize="36" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<TextBlock x:Name="txtTime" Grid.Row="1" TextWrapping="Wrap" FontSize="180" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
Usercontrol
<UserControl
x:Class="AlarmPro.TimeOnCity"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AlarmPro"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="150"
d:DesignWidth="250">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="#FFDE6A6A" BorderThickness="1" Grid.Row="0" Grid.Column="0" Background="#FFDC4646">
<TextBlock TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16"/>
</Border>
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" Background="#FFAE4F00">
<TextBlock TextWrapping="Wrap" Text="TextBlock" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="36"/>
</Border>
</Grid>
</UserControl>
Do you mean like this?
<my:UserControlName Grid.Column="2" Grid.Row="2" ... />
<my: in this case is the alias for the CLR namespace the UserControl resides in. It is defined at the top of your XAML, inside the <Window> or <UserControl> tag depending on context.
For example,
<Window ...
xmlns:my="clr-namespace:AssemblyName"
...
/>
MainPage.Xaml
<Page
x:Class="UserControlExample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UserControlExample"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="MainContent" Background="Azure" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="1" HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden">
<local:UserControl1 x:Name="MyHelloWorldUserControl" Grid.Row="1" />
</ScrollViewer>
</Grid>
</Page>
UserControl1.xaml
<UserControl
x:Class="UserControlExample.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:UserControlExample"
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 Background="Bisque">
<StackPanel>
<StackPanel Orientation="Horizontal" Height="81">
<TextBlock Text="Your Name is" Foreground="Blue" FontSize="30" Margin="0,0,0,10"/>
<TextBox x:Name="Input" Background="White" Width="225" />
</StackPanel>
<Button Content="Click Me" Foreground="Brown" FontSize="30" Click="Button_Click"/>
<TextBlock x:Name="Output" FontSize="100"/>
</StackPanel>
</Grid>
</UserControl>
MainPage.xaml, I am binding a login UserControl
by using the namespace : xmlns:UC="clr-namespace:Test.Views" , since I have my usercontrol in Folder named "Views".
<ScrollViewer>
<UC:Login BtnLoginClick="Login_BtnLoginClick"/>
</ScrollViewer>
Login.cs
public partial class Login : UserControl {
public event EventHandler BtnLoginClick;
public Login()
{
InitializeComponent();
}
private void btnLogin_Click(object sender, RoutedEventArgs e)
{
string userName = txtUserName.Text;
string userPassword = txtUserPassword.Password.Trim();
if (userName != null && userName != string.Empty && userPassword != null && userPassword != string.Empty)
{
if (this.BtnLoginClick != null)
{
this.BtnLoginClick(this, e);
}
}
else
{
MessageBox.Show("Invalid username or password");
}
}
}
Finally, dont forgot to use the event handler in MainPage.xaml to capture the button clicked event from Login Usercontrol to do other actions.
MainPage.xaml
<UC:Login BtnLoginClick="Login_BtnLoginClick"/>
Here "BtnLoginClick" its an event Handler defined in the Login.xaml[User Control].
Create new event for this "BtnLoginClick" event as i created "Login_BtnLoginClick".
MainPage.cs
private void Login_BtnLoginClick(object sender, EventArgs e)
{
Messagebox.Show("Event captured successfully");
////Here you can add your stuffs...
}
For UWP, in UserControl.xaml, find the local namespace xmlns:local notation: xmlns:local="using:ProjectName.Folder" at the top (by convention, C# namespaces are named the same way as the folder that contains them, so folder also means namespace).
In MainPage.xaml, add a reference to this namespace. The reference prefix can be any name desired: for example, CustomPrefix, as in xmlns:CustomPrefix="using:ProjectName.Folder". Then, anywhere in MainPage.xaml, display the control by prefixing its name with <CustomPrefix:...>.
UserControl.xaml
<UserControl
xmlns:local="using:ProjectName.Folder">
MainPage.xaml
<Page
xmlns:CustomPrefix="using:ProjectName.Folder">
<CustomPrefix:UserControl />
</Page>
The project needs to be built to discard XAML errors in Visual Studio, otherwise the design view remains blank and the XAML has green squiggles.