How to use Xaml inheritance in WinUI 3? - xaml

Judging from answers like this it looks like xaml inheritance works for WPF and UWP.
Does it work for WinUI 3?
Using code like this:
<local:YourBaseClass x:Class="MyApp.ChildClass"
...
xmlns:local="clr-namespace:MyApp">
</local:YourBaseClass>
I get the error:
Error WMC0001 Unknown type 'YourBaseClass' in XML namespace 'clr-namespace:MyApp'

Does it work for WinUI 3?
Yes. It almost exactly the same.
Create the base class that inherits from Microsoft.UI.Xaml.Window:
public class YourBaseClass : Microsoft.UI.Xaml.Window
{
public YourBaseClass() : base()
{
Title = "Title...";
}
}
Modify MainWindow.xaml.cs to inherit from the new base class:
public sealed partial class MainWindow : YourBaseClass
{
public MainWindow()
{
this.InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
myButton.Content = "Clicked";
}
}
Modify the root element in MainWindow.xaml:
<local:YourBaseClass
x:Class="WinUI3App.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI3App"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
</StackPanel>
</local:YourBaseClass>

Related

How can I Set Xaml code behind property from it's own XAML. e.g "this"

I have my Xamarin forms MasterDetailPage Xaml code-behind .xaml.cs file where I created a string property.
I want to set that property from the front-end Xaml.
I know it seems like a newbe question, but for crying-out-loud I can't get anything to work.
Does anyone know how to do this?
E.g.
this.stringProperty = "string" IN XAML markup.
Or pseudo-code
{RelativeSource Self}.stringProperty ="string"
Thanks
#TRS
Let me clarify by using your code. I only need the first part of your code.
public partial class MainWindow : Window <-- YOUR CODE
{
private testString; <-- ADDED THIS
public MainWindow()
{
InitializeComponent();
DataContext = new MyClass(); <-- REMOVED THIS
public string TestString; <-- ADDED THIS
{
get => testString;
set
{
testString; = value;
}
}
}
Now I want to set the "TestString" property from this same partial class's MainWindow XAML.
<Window x:Class="WpfApp6.MainWindow"
x:Name="Mywindow"
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:WpfApp6"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
SET TestString PROPERTY IN THE CODE BEHIND HERE IN THE XAML
So, with that in mind. How can I do it?
Here is minimal working example for you .But you have to read about DataContext, INotifyPropertyChanged and MVVM to understand it thoroughly,otherwise you will have many questions.Keep you code behind clean.
<Window x:Class="WpfApp6.MainWindow"
x:Name="Mywindow"
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:WpfApp6"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding MyString}"></TextBlock>
</Grid>
and code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MyClass();
}
}
public class MyClass : INotifyPropertyChanged
{
private string _myString;
public string MyString
{
get => _myString;
set
{
_myString = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

Xamarin forms (Cross-Platform) : Multiple type of cells in ListView

I am new to Xamarin. I have a requirement where I have to implement a ListView or say tableView that have multiple different type-size cells.
And I also have to add Header for a particular section of cells, and some of my custom cells have a horizontal scroll in it.
I have done this thing in iOS native UITableView before, but don't know how this done in Xamarin cross platform, can anyone help me out this?
You are looking for DataTemplateSelector, which is very well documented in the official Xamarin.Forms documentation.
The basics are that you create your own DataTemplateSelector class:
public class MyDataTemplateSelector : DataTemplateSelector
{
}
In that class you override OnSelectTemplate:
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
}
By checking the type of the item argument, you should be able to figure out which template to return.
So lets say you have a ViewModel for Dog and one for Cat and want to show a different DataTemplate for each of those. You would do something like:
public class DogCatTemplateSelector : DataTemplateSelector
{
public DataTemplate DogTemplate { get; set; }
public DataTemplate CatTemplate { get; set; }
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
{
if (item is DogViewModel)
return DogTemplate;
return CatTemplate;
}
}
Then you can consume this in your XAML:
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="dogTemplate">
<ViewCell>
... <---- define your look of dog template here
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="catTemplate">
<ViewCell>
... <---- define your look of cat template here
</ViewCell>
</DataTemplate>
<local:DogCatTemplateSelector x:Key="dogCatTemplateSelector"
DogTemplate="{StaticResource dogTemplate}"
CatTemplate="{StaticResource catTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
Then simply set the ItemTemplate to your dogCatTemplateSelector instance you've defined in the resources on your ListView:
<ListView ItemsSource="{Binding DogsCatsCollection}" ItemTemplate="{StaticResource dogCatTemplateSelector}" />
Your ViewModel would then look something like:
public class Animal : INotifyPropertyChanged
{
}
public class DogViewModel : Animal
{
}
public class CatViewModel : Animal
{
}
public class MainViewModel : INotifyPropertyChanged
{
public ObservableCollection<Animal> DogsCatsCollection { get; }
= new ObservableCollection<Animal>();
}
Then you just populate DogsCatsCollection with instances of dogs and cats.

Xamarin.Forms: How to set BindingContext inside XAML?

I have the following page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:XamFormsBle.Pages;assembly=XamFormsBle"
x:Name="ContentPageContainer"
x:Class="XamFormsBle.Pages.ConnectPage">
<!--This does not work-->
<ContentPage.BindingContext>
<pages:ConnectPage/>
</ContentPage.BindingContext>
<StackLayout Orientation="Vertical">
<Button Text="Refresh"
Clicked="RefreshDevicesList"/>
<ListView ItemsSource="{Binding DevicesList}"/>
</StackLayout>
</ContentPage>
And the code behind:
public partial class ConnectPage : ContentPage
{
public ObservableCollection<string> DevicesList { get; set; }
public ConnectPage()
{
InitializeComponent();
DevicesList = new ObservableCollection<string>();
//BindingContext = this;
}
public void RefreshDevicesList(object sender, EventArgs e)
{
DevicesList.Add("device");
}
}
What I am trying to achieve is to bind the ListView to the DevicesList. It works when I uncomment the BindingContext line in the constructor. I want to move that line into the .xaml itself. Researching the matter leads to the ContentPage.BindingContext block in the .xaml, but that crashes the program. There also seems to be the approach of setting the Source inside the binding of the ListView's ItemsSource, but I don't understand the syntax to work it in my case (I'm new to Xamarin.Forms and XAML in general). Is there a way to set the BindingContext inside .xaml?
You're using MVVM wrong. You're trying to set viewmodel to the view itself. Create a seperate class for the viewmodel, and it shouldn't be deriving from a ContentPage as you did.

[UWP][C++/CX] Cannot access XAML UI from codebehind

C++:
#include "pch.h"
#include "MainPage.xaml.h"
using namespace Testing;
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::UI::Xaml::Controls::Primitives;
using namespace Windows::UI::Xaml::Data;
using namespace Windows::UI::Xaml::Input;
using namespace Windows::UI::Xaml::Media;
using namespace Windows::UI::Xaml::Navigation;
MainPage::MainPage()
{
InitializeComponent();
}
void Testing::MainPage::Page_SizeChanged(Platform::Object^ sender,Windows::UI::Xaml::SizeChangedEventArgs^ e)
{
SplitPane->isPaneOpen = !SplitPane->isPaneOpen; //LEGAL
}
void test()
{
SplitPane->isPaneOpen = !SplitPane->isPaneOpen; //NOT LEGAL
}
XAML:
<Page
x:Class="Testing.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Testing"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
SizeChanged="Page_SizeChanged">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<SplitView Name="SplitPane">
</SplitView>
</Grid>
So my question is why i cant use a reference or rather find the reference of the SplitView in my function? and is there a solution?
I find it a bit ugly to pass SplitPane as parameter
P.S. in C# test() is completely legal
In order to use the private fields of a MainPage, test() must be a method of the MainPage class.
In MainPage.xaml.h:
public ref class MainPage sealed
{
public:
MainPage();
void test();
};
In MainPage.xaml.cpp:
void MainPage::test()
{
SplitPane->IsPaneOpen = !SplitPane->IsPaneOpen; // LEGAL
}

How can I specify a ViewModel to a XAML window?

I am trying to share a ViewModel between XAML windows. This is necessary to allow multiple views of the object instance to receive events from the ViewModel.
Specifying the ViewModel as a resource in the XAML, then overwriting it in an alternate constructor does not work. The binding will still be to the default instance created in the default constructor and will not receive events from or update the proper instance.
This does not work:
MyWindow.xaml:
<Window x:Class="MyNamespace.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Title="My Window"
Width="700" Height="550">
<Window.Resources>
<local:MyViewModel x:Key="MyModel"/>
</Window.Resources>
<ContentPresenter Content="{StaticResource MyModel}"/>
</Window>
MyWindow.xaml.cs
imports ...;
namespace MyNamespace {
public partial class MyWindow {
public MyWindow() {
InitializeComponent();
}
public MyWindow(MyViewModel model)
: this() {
Resources["MyModel"] = model;
}
}
}
Nor will this:
MyWindow.xaml.cs
imports ...;
namespace MyNamespace {
public partial class MyWindow {
public MyWindow()
: this(new MyViewModel()) { }
public MyWindow(MyViewModel model) {
Resources["MyModel"] = model; // Resources not yet initialized!
InitializeComponent();
}
}
}
if you are using Microsoft.Practices.Unity you can use TransientLifetimeManager.It will make sure that only one object of your viewmodel is created.
MyThis can be done by using properties on the code-behind and using the Binding tag in the XAML rather than StaticResource as follows:
MyWindow.xaml:
<Window x:Class="MyNamespace.MyWindow"
x:Name="this"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyNamespace"
Title="My Window"
Width="700" Height="550">
<ContentPresenter Content="{Binding MyModel, ElementName=this}"/>
</Window>
MyWindow.xaml.cs
imports ...;
namespace MyNamespace {
public partial class MyWindow {
public MyViewModel MyModel { get; private set; }
public MyWindow()
: this(new MyViewModel()) { }
public MyWindow(MyViewModel model) {
MyModel = model;
InitializeComponent();
}
}
}
Multiple windows (or other components) can use the same model instance.
Edit 06-Dec-12:
The XAML was not correct and the binding would not work. Added the x:Name attribute to the root element (Window), and added the ElementName argument to the Content attribute of the bound element (ContentPresenter).