XAML Reuse a block of markup - c#

Consider I have multiple pages and I want to show the same "Header" in every page without copying & pasting it multiple times: it's very unmaintainable.
<!-- #region Header -->
<Grid Grid.Row="0">
<Rectangle Style="{StaticResource HeaderBackground}" />
<TextBlock
Style="{StaticResource PageTitle}"
Text="Page1" />
<Button
Content="Settings"
Command="{Binding GotoSettingsPage}" />
</Grid>
<!-- #endregion Header -->
What are the options to make this block of markup reusable? For example it would be nice to write something like this:
<MyHeader Grid.Row="0" PageTitle="Page1" />

A user control is an option.
MyHeader.Xaml:
<UserControl
x:Class="App1.MyHeader"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
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>
<Rectangle Style="{StaticResource HeaderBackground}" />
<TextBlock x:Name="Title"
Style="{StaticResource PageTitleStyle}"
Text="" />
<Button Content="Settings"
Command="{Binding GotoSettingsPage}"/>
</Grid>
</UserControl>
MyHeader.Xaml.cs:
using Windows.UI.Xaml.Controls;
namespace App1
{
public sealed partial class MyHeader : UserControl
{
public MyHeader()
{
this.InitializeComponent();
}
public string PageTitle
{
get { return Title.Text; }
set { Title.Text = value ?? ""; }
}
}
}
MainPage.Xaml:
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<local:MyHeader PageTitle="Page 1"/>
</Grid>
</Page>

Related

adding a image to button programmatically with text content [duplicate]

Cant make button in WPF app with image and text on it. My code is like this:
<Window x:Class="WindowR.One"
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:WindowR"
mc:Ignorable="d"
Title="One" Height="300" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<TextBlock Text="Click Here" />
<Image Source="D:\Skola\4. semester\TP\GIT folder\Visualko\Core\WindowR\Pictures\0.png" />
</StackPanel>
</Grid>
</Window>
But the text isnt above image..tried lots of tutorials from here..but none of them work properly
StackPanel arranges TextBlock next to Image. Try to use Grid
<Button Width="120" Height="50" >
<Grid>
<Image Source="D:\Skola\4. semester\TP\GIT folder\Visualko\Core\WindowR\Pictures\0.png" />
<TextBlock Text="Click Here"
VerticalAlignment="Center"
HorizontalAlignment="Center" />
</Grid>
</Button>

How to load user components in a panel on click of buttons?

I have two panels which are added to a user control (SalesLandingPage).
In column2, i have a user control SaleOrderCommandOptions which has a stack panel with 2 buttons (order & checkout)
On order click, I need to show orderUserControl in column1 of SalesLandingPage ...
and similarly on clicking checkout, I need to show checkoutUserControl in column1 of SalesLandingPage.
Can anyone guide me on how to achieve the same?
Below is the code -
MainWindow.xaml
<telerik:RadTabbedWindow x:Class="WPFInterplayPOS.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:userControls="clr-namespace:WPFInterplayPOS.UserInterface.Sales"
xmlns:local="clr-namespace:WPFInterplayPOS" WindowState="Maximized" Height="513.424" Width="844.321"
AddButtonVisibility="Hidden" HideMinimizeButton="True" HideMaximizeButton="True" ResizeMode="NoResize">
<telerik:RadTabItem Header="Sales" CloseButtonVisibility="Hidden" HorizontalContentAlignment="Right">
<userControls:SalesLandingPage></userControls:SalesLandingPage>
</telerik:RadTabItem>
</telerik:RadTabbedWindow>
SalesLandingPage.xaml
<UserControl x:Class="WPFInterplayPOS.UserInterface.Sales.SalesLandingPage"
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:WPFInterplayPOS.UserInterface.Sales"
xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
xmlns:telerikPresentation="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<!-- Grid layout column definitions -->
<Grid.ColumnDefinitions>
<ColumnDefinition Width="8*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- RadNavigationView in column 0 -->
<telerik:RadNavigationView x:Name="navigationView" Grid.Column="0" DisplayMode="Compact" AutoChangeDisplayMode="False" PaneToggleButtonVisibility="Hidden">
<telerik:RadNavigationView.Items>
<telerik:RadNavigationViewItem>
<telerik:RadNavigationViewItem.Icon>
<telerikPresentation:RadGlyph Glyph="" FontSize="16"/>
</telerik:RadNavigationViewItem.Icon>
</telerik:RadNavigationViewItem>
<telerik:RadNavigationViewItem>
<telerik:RadNavigationViewItem.Icon>
<telerikPresentation:RadGlyph Glyph="" FontSize="16"/>
</telerik:RadNavigationViewItem.Icon>
</telerik:RadNavigationViewItem>
<telerik:RadNavigationViewItem>
<telerik:RadNavigationViewItem.Icon>
<telerikPresentation:RadGlyph Glyph="" FontSize="16"/>
</telerik:RadNavigationViewItem.Icon>
</telerik:RadNavigationViewItem>
</telerik:RadNavigationView.Items>
<telerik:RadNavigationView.Content>
<TextBlock Text="Content" Foreground="Black" Margin="5"/>
</telerik:RadNavigationView.Content>
</telerik:RadNavigationView>
<!-- column 1 -->
<StackPanel x:Name="SaleOrderCommandView" Grid.Column="1">
<!-- Display relevant user control here based on button click in SaleOrderCommandOptions user control -->
</StackPanel>
<!-- SaleOrderCommandOptions in column 2 -->
<local:SaleOrderCommandOptions Grid.Column="2">
</local:SaleOrderCommandOptions>
</Grid>
</UserControl>
SaleOrderCommandOptions.xaml
<UserControl x:Class="WPFInterplayPOS.UserInterface.Sales.SaleOrderCommandOptions"
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:telerikPresentation="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:telerik="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"
xmlns:local="clr-namespace:WPFInterplayPOS.UserInterface.Sales"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Telerik.Windows.Controls;component/Themes/FontResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel Grid.Column="2" Background="{telerikPresentation:MaterialResource ResourceKey=PrimaryHoverBrush}">
<telerik:RadButton>Order</telerik:RadButton>
<telerik:RadButton>Checkout</telerik:RadButton>
</StackPanel>
</UserControl>

how to run a dialog from the code?

i'm coding a c# application using material design
here is my UserControl's xaml code :
<UserControl
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:MediCare"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes" x:Name="Usc1" "
mc:Ignorable="d" Height="900" Width="600">
<materialDesign:DialogHost x:Name="Dialog" >
<materialDesign:DialogHost.DialogContent>
<Grid Width="300" Height="100">
<TextBlock Text="DIALOG TEST"/>
<Button Command="{x:StaticmaterialDesign:DialogHost.CloseDialogCommand}" Content="CloseDialog"/>
</Grid>
</materialDesign:DialogHost.DialogContent>
<Grid>
<Button Command="{x:Static materialDesign:DialogHost.OpenDialogCommand}" Content="CloseDialog" />
</Grid>
</materialDesign:DialogHost>
i've a button with the command Command="{x:Static
materialDesign:DialogHost.OpenDialogCommand}" to open my dialog, but my purpose is to open it through the .xaml.cs, how can i do ?
I got the dialog to show using Dialog.IsOpen = true;

Using commands in wpf is not working properly for a button

There is a button in the following xaml code:
<Button Grid.Row="1" x:Name="First" Content="First" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="40,91,0,67" />
In the constructor of the window I have assigned ApplicationCommands.Copy to the button.
public MainWindow()
{
InitializeComponent();
this.doc.Unit = DevExpress.Office.DocumentUnit.Point;
this.First.Command = ApplicationCommands.Copy;
First.CommandTarget = this.doc;
}
this.doc in the above code is a typical richTextBox.
The problem is that the button is always disabled. Why?
The entire xaml code is as follows:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:com="clr-namespace:DevExpress.XtraRichEdit.Commands;assembly=DevExpress.RichEdit.v16.1.Core"
xmlns:dxre="http://schemas.devexpress.com/winfx/2008/xaml/richedit" xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors" xmlns:ig="http://schemas.infragistics.com/xaml" xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core" x:Class="WpfApplication1.MainWindow"
Title="MainWindow" Height="700" Width="1000" x:Name="wnd">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="163*" />
<RowDefinition Height="60*" />
</Grid.RowDefinitions>
<dxre:RichEditControl x:Name="doc" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,0,0,23" Unit="Point" ActiveViewType="PrintLayout"/>
<!--<telerik:RadToggleButton
Content="B" HorizontalAlignment="Left" Height="Auto" IsThreeState="False" IsChecked="False" Margin="10,32,0,0" Grid.Row="1" VerticalAlignment="Top" Width="26"/>-->
<Button Grid.Row="1" x:Name="First" Content="First" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="40,91,0,67" />
</Grid></Window>
The Button.Command property is a type if ICommand, which includes a CanExecute method. When this method returns false the Button will be disabled.
I believe that's what's happening here, the ApplicationCommands.Copy command is returning false for CanExecute. Perhaps someone else can offer an explanation as to why this is in this case?
Are you able to use a CommandBinding as described here to implement your own CanExecute event handler?
<Window x:Class="WCSamples.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CloseCommand"
Name="RootWindow"
>
<Window.CommandBindings>
<CommandBinding Command="ApplicationCommands.Copy"
CanExecute="CanExecuteHandler"
/>
</Window.CommandBindings>
<StackPanel Name="MainStackPanel">
<Button Command="ApplicationCommands.Copy"
Content="Copy" />
</StackPanel>
</Window>
private void CanExecuteHandler(object sender, CanExecuteRoutedEventArgs e)
{
// CanExecute logic in here.
e.CanExecute = true;
}

Binding into another usercontrol

I just started working with WPF and I'm trying to wrap my head around the XAML Bindings.
After a lot of reading I thought I had an easy enough usecase to test my knowledge. But nada :-( I can't figure it out.
What I'm trying to do is the following:
I have Address-Objects:
public IEnumerable<Address> Addresses
{
get
{
if (addresses == null)
{
addresses = new Repository<Address>().GetAll().ToList<Address>();
}
return addresses;
}
}
which have Rental-Objects e.g.
address.Rentals
also as IList.
On my MainWidow I want to have 2 UserControls, one for the address and one for the rental information. If I click the Navigator on the address user control, I only want to see the rental records of the current address.
MainWindow
<Window x:Class="Swopt.Mira.WPFApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:Swopt.Mira.WPFApp"
Title="MainWindow" Height="500" Width="525">
<Window.Resources>
<sampleData:DataContext x:Key="testDataContext" />
</Window.Resources>
<Grid x:Name="rootGrid" Background="White" DataContext="{StaticResource testDataContext}">
<StackPanel>
<local:RentalCustomer x:Name="rentalCustomer" Height="100" />
<local:Rentals Height="100" />
</StackPanel>
</Grid>
Address
<UserControl
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:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="Swopt.Mira.WPFApp.RentalCustomer"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="RentalCustomerUserControl">
<Grid x:Name="rootGrid" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<StackPanel>
<TextBlock Text="Firma1"/>
<TextBox x:Name="Firma1" Text="{Binding ElementName=collectionNavigator, Path=CurrentItem.Firma1}" />
</StackPanel>
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
Grid.ColumnSpan="2"
x:Name="collectionNavigator"
Source="{Binding Addresses}"
/>
</Grid>
Rentals
<UserControl
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:telerik="http://schemas.telerik.com/2008/xaml/presentation" x:Class="Swopt.Mira.WPFApp.Rentals"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="RentalsUserControl">
<Grid x:Name="rootGrid" Background="White" >
<StackPanel>
<TextBlock Text="VertragsNr"/>
<TextBox x:Name="VertragsNr" Text="{Binding ElementName=collectionNavigator2, Path=CurrentItem.VertragsNr}" />
</StackPanel>
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
x:Name="collectionNavigator2"
Source="{Binding Rentals}" />
</Grid>
Essentially what I want to do is Bind the DataContext of UserControl2 (Rentals) to the CurrentItem of collectionNavigator in UserControl1 (Addresses)
But I can't figure out how. I tried many things, with Binding Path and RelativeSource but none seem to work. the only way I could get it to work was to copy the content of UserControl1 into my MainWindow.xaml, but then I can't reuse it.
Any help is much appreciated.
UPDATE >>>>>
Working solution from Sheridan.
MainWindows
...
<local:RentalCustomer x:Name="rentalCustomer" Height="400" />
<local:Rentals Height="100" DataContext="{Binding CurrentAddress, ElementName=rentalCustomer}" />
RentalCustomer.xaml
...
<telerik:RadCollectionNavigator Grid.Row="1"
Height="30"
Margin="2"
Grid.ColumnSpan="2"
x:Name="collectionNavigator"
Source="{Binding Addresses}"
CurrentItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=CurrentAddress, Mode=OneWayToSource}"
/>
RentalCustomer.xaml.cs
public Address CurrentAddress
{
get { return (Address)GetValue(CurrentAddressProperty); }
set { SetValue(CurrentAddressProperty, value); }
}
// Using a DependencyProperty as the backing store for CurrentAddress. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CurrentAddressProperty =
DependencyProperty.Register("CurrentAddress", typeof(Address), typeof(RentalCustomer), new PropertyMetadata(null));
You can data bind the current item of a collection using the "/" Binding notation. Try something like this:
<UserControl Name="Control1" DataContext="{Binding SomeCollection}" />
<UserControl Name="Control2" DataContext="{Binding SomeCollection/}" />
Binding SomeCollection/ means bind to the current item of the SomeCollection collection. To make this work, you may need to set the Selector.IsSynchronizedWithCurrentItem Property to True on any container controls that you are selecting the current item in:
<ListBox ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" ... />
UPDATE >>>
Without an IsSynchronizedWithCurrentItem property, the "/" Binding notation won't work. Instead, you could expose the selected item from the collection as a DependencyProperty on the relevant UserControl. Then you could do something like this:
<UserControl Name="Control2" DataContext="{Binding SelectedItem, ElementName=Control1}" />
You could provide the Rentals from your viewModel by binding the CurrentItem to your viewModel and expose the Rentals like this:
<telerik:RadCollectionNavigator CurrentItem={Binding CurrentItem} />
public Address CurrentItem
{
get; set;
}
public IEnumerable<Rentals> Rentals
{
get { return CurrentItem.Rentals; }
}

Categories

Resources