How to get the DisplayName of the package in C++/WinRT? - xaml

i would like to get the DisplayName of the package in C++/WinRT.
As describe in this C# example:
<TextBlock x:Name="AppTitle"
Text="{x:Bind GetAppTitleFromSystem()}"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}" />
namespace AppUIBasics
{
public sealed partial class NavigationRootPage : Page
{
public string GetAppTitleFromSystem()
{
return Windows.ApplicationModel.Package.Current.DisplayName;
}
}
}
i tried to :
// .xaml.h file
struct MainWindow : MainWindowT<MainWindow>
{
MainWindow();
winrt::hstring GetAppTitleFromSystem();
}
...
// .xaml.cpp file
...
MainWindow::MainWindow()
{
InitializeComponent();
}
hstring MainWindow::GetAppTitleFromSystem()
{
Package package = Package::Current();
return package.DisplayName();
}
...
// .idl
namespace Example
{
[default_interface]
runtimeclass MainWindow : Microsoft.UI.Xaml.Window
{
MainWindow();
String GetAppTitleFromSystem{ get; };
}
}
i got error like:
2.Error XLS0525 Method 'GetAppTitleFromSystem' not found in type 'MainWindow. Example C:\Users\{..}\MainWindow.xaml 72

Related

How to get a value from custom control in a broader control via binding in VM

MAUI.NET
I have a special picker for my own that I want to reuse in many places
<ContentView ...
x:Class="XYZ.Views.ABCPicker"
x:DataType="views:ABCPicker">
<Grid>
<Picker ItemsSource="{Binding ...}" SelectedItem="{Binding ChoosenDeviceTypeProperty}"/>
</Grid>
</ContentView>
and its code behind with my AttachedProperty:
public partial class ABCPicker : ContentView
{
public static readonly BindableProperty ChoosenDeviceTypeProperty = BindableProperty.CreateAttached("ChoosenDeviceType", typeof(string), typeof(ABCPicker), "Detect by connect", BindingMode.TwoWay);
public static string GetChoosenDeviceType(BindableObject view)
{
return (string)view.GetValue(ChoosenDeviceTypeProperty);
}
public static void SetChoosenDeviceType(BindableObject view, string value)
{
view.SetValue(ChoosenDeviceTypeProperty, value);
}
public ABCPicker()
{
this.BindingContext = this;
InitializeComponent();
}
}
I want to consume it in my broader control ViewModel
public class BroaderControlViewModel : BaseViewModel
{
...
private string myResult;
public string MyResult
{
get { return myResult; }
set { SetPropertyAndNotify(ref myResult, value); }
}
public ICommand MyCommand { private set; get; }
public BroaderControlViewModel()
{
MyCommand = new Command(() =>
{
// here I want the to get a choosen value to proceed with it after the user have choosen value in my special picker
});
}
}
with a view like below:
<ContentView ...
x:Class="XYZ.Views.BroaderControlView"
x:DataType="viewModels:BroaderControlViewModel">
<VerticalStackLayout ...>
<views:ABCPicker ChoosenDeviceType="{Binding MyResult, Mode=TwoWay}" />
<Button Text="Connect" Command="{Binding MyCommand}"/>
</VerticalStackLayout>
</ContentView>
I tried different binding types, also with x:Reference this and also with normal binding properties - not attached ones.
How it should be matched?

How to bind an object to a view programmatically using WinUI3 with C++/WinRT?

I am using WinUI3 with C++/WinRT and I am trying to bind an object like "User" to a collection like "ListViewItem".
Below you can see the xaml and the code behind creating a list view item and the binding part.
XAML:
<StackPanel>
<Button x:Name="button" Click="button_Click" Content="Add" />
<ListView x:Name="listView" />
</StackPanel>
CPP:
class User : public ::winrt::Microsoft::UI::Xaml::Data::INotifyPropertyChanged
{
public:
User() {}
~User() {}
void Name(const ::winrt::hstring& aName) {
if (mName != aName) {
mName = aName;
mPropertyChanged(*this, ::winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventArgs{ L"Name" });
}
}
::winrt::hstring Name() {
return mName;
}
::winrt::event_token PropertyChanged(::winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler const& aHandler) {
return mPropertyChanged.add(aHandler);
}
void PropertyChanged(::winrt::event_token const& aToken) noexcept {
mPropertyChanged.remove(aToken);
}
private:
::winrt::hstring mName = L"NoName";
event<::winrt::Microsoft::UI::Xaml::Data::PropertyChangedEventHandler> mPropertyChanged;
};
::winrt::Microsoft::UI::Xaml::Controls::ListViewItem CreateLVI() {
::winrt::Microsoft::UI::Xaml::Controls::TextBlock myText;
User myDataObject;
::winrt::Microsoft::UI::Xaml::Data::Binding myBinding;
myBinding.Path(::winrt::Microsoft::UI::Xaml::PropertyPath(L"Name"));
myBinding.Source(myDataObject);
::winrt::Microsoft::UI::Xaml::Data::BindingOperations::SetBinding(myText, ::winrt::Microsoft::UI::Xaml::Controls::TextBlock::TextProperty(), myBinding);
::winrt::Microsoft::UI::Xaml::Controls::ListViewItem lvi;
lvi.Content(myText);
return lvi;
}
MainWindow::MainWindow()
{
InitializeComponent();
}
void MainWindow::button_Click(::winrt::Windows::Foundation::IInspectable const& sender, ::winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
listView().Items().Append(CreateLVI());
}
But it doesnt work, the user's name doesnt show in the list view item. The list view item is created tho.

Xamarin forms Shell Custom icon for selected tab

I'm playing with the COOL xamarin shell, but I didn't found a way to change icon of the selected tab.
<TabBar Route="sections">
<Tab Title="home">
<Tab.Icon>
<FontImageSource FontFamily="{StaticResource AppIcons}" Glyph="{x:Static framework:Icons.HomePage}" />
</Tab.Icon>
<ShellContent ContentTemplate="{DataTemplate home:HomePage}" Route="home" />
</Tab>
The goal is to use Icons.HomePageFilled instead of Icons.HomePage for this tab only when it's selected. Same logic should apply to other tabs.
I think I got lost in the solutions found on the web. They talk about Custom renderers(ShellTabLayoutAppearanceTracker), Visual states, effects etc ...
But I do not know if it is feasible and what is the ideal solution
You need to use custom renderer of shell to customize the tabbar selected icon on each platform.
In iOS, override the CreateTabBarAppearanceTracker method:
[assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
namespace App30.iOS
{
public class MyShellRenderer : ShellRenderer
{
protected override IShellSectionRenderer CreateShellSectionRenderer(ShellSection shellSection)
{
var renderer = base.CreateShellSectionRenderer(shellSection);
if (renderer != null)
{
}
return renderer;
}
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new CustomTabbarAppearance();
}
}
public class CustomTabbarAppearance : IShellTabBarAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(UITabBarController controller)
{
}
public void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
UITabBar myTabBar = controller.TabBar;
if (myTabBar.Items != null)
{
UITabBarItem itemOne = myTabBar.Items[0];
itemOne.Image = UIImage.FromBundle("tab_about.png");
itemOne.SelectedImage = UIImage.FromBundle("tab_feed.png");
UITabBarItem itemTwo = myTabBar.Items[1];
itemTwo.Image = UIImage.FromBundle("tab_feed.png");
itemTwo.SelectedImage = UIImage.FromBundle("tab_about.png");
//The same logic if you have itemThree, itemFour....
}
}
public void UpdateLayout(UITabBarController controller)
{
}
}
}
In Android, override the CreateBottomNavViewAppearanceTracker method:
[assembly: ExportRenderer(typeof(AppShell), typeof(MyShellRenderer))]
namespace App30.Droid
{
public class MyShellRenderer : ShellRenderer
{
public MyShellRenderer(Context context) : base(context)
{
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new CustomBottomNavAppearance();
}
}
public class CustomBottomNavAppearance : IShellBottomNavViewAppearanceTracker
{
public void Dispose()
{
}
public void ResetAppearance(BottomNavigationView bottomView)
{
}
public void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
{
IMenu myMenu = bottomView.Menu;
IMenuItem myItemOne = myMenu.GetItem(0);
if (myItemOne.IsChecked)
{
myItemOne.SetIcon(Resource.Drawable.tab_about);
}
else
{
myItemOne.SetIcon(Resource.Drawable.tab_feed);
}
//The same logic if you have myItemTwo, myItemThree....
}
}
}
I uploaded a sample project here and you can check it.

How to two way bind to a UserControl DependencyProperty?

I am making a custom slider called scalar_slider using a UserControl. I would like to two way bind one of it's DependencyProperty.
The problem is that the value changes made inside scalar_slider are not updated back to the parent's view model vm which correctly implements INotifyPropertyChanged. I assume the problem has to do with how I am setting the binding in MainPage.xaml.
// MainPage.xaml
<local:scalar_slider scalar_value="{x:Bind vm.my_scalar_value Mode=TwoWay}" />
// scalar_slider.xaml
<UserControl
x:Class="transformations.scalar_slider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:transformations"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel>
<TextBox Text="{x:Bind scalar_value, Mode=TwoWay}"/>
<Slider Value="{x:Bind scalar_value, Mode=TwoWay}"/>
</StackPanel>
</UserControl>
//scalar_slider.idl
namespace transformations
{
[default_interface]
runtimeclass scalar_slider : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
scalar_slider();
static Windows.UI.Xaml.DependencyProperty scalar_valueProperty;
Single scalar_value;
}
}
//scalar_slider.h
namespace winrt::transformations::implementation
{
struct scalar_slider : scalar_sliderT<scalar_slider>
{
scalar_slider();
static Windows::UI::Xaml::DependencyProperty scalar_valueProperty();
static void scalar_valueProperty(Windows::UI::Xaml::DependencyProperty value);
float scalar_value();
void scalar_value(float value);
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
template <class T>
void update_value(hstring const& property_name, T & var, T value)
{
if (var != value)
{
var = value;
raise_property_changed(property_name);
}
}
private:
event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_property_changed;
void raise_property_changed(hstring const& property_name)
{
m_property_changed(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs(property_name));
}
static Windows::UI::Xaml::DependencyProperty m_scalar_value_property;
float m_scalar_value = 0.0f;
};
}
//scalar_slider.cpp
namespace winrt::transformations::implementation
{
scalar_slider::scalar_slider()
{
InitializeComponent();
}
winrt::event_token scalar_slider::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_property_changed.add(handler);
}
void scalar_slider::PropertyChanged(winrt::event_token const& token) noexcept
{
m_property_changed.remove(token);
}
Windows::UI::Xaml::DependencyProperty scalar_slider::m_scalar_value_property = Windows::UI::Xaml::DependencyProperty::Register(
L"scalar_value",
winrt::xaml_typename<float>(),
winrt::xaml_typename<winrt::transformations::scalar_slider>(),
Windows::UI::Xaml::PropertyMetadata{ nullptr }
);
Windows::UI::Xaml::DependencyProperty scalar_slider::scalar_valueProperty()
{
return m_scalar_value_property;
}
void scalar_slider::scalar_valueProperty(Windows::UI::Xaml::DependencyProperty value)
{
m_scalar_value_property = value;
}
float scalar_slider::scalar_value()
{
return m_scalar_value;
}
void scalar_slider::scalar_value(float value)
{
update_value(L"scalar_value", m_scalar_value, value);
}
}
About your code, I find the get and set function of scalar_slider property you write are not correct in scalar_slider.cpp, you can change them like below code.
You can also read XAML custom (templated) controls with C++/WinRT to understand better.
float scalar_slider::scalar_value()
{​
return winrt::unbox_value<float>(GetValue(m_scalar_value_property));​
}​
​
void scalar_slider::scalar_value(float value)​
{​
SetValue(m_scalar_value_property, winrt::box_value(value));​
m_property_changed(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs(L"scalar_value"));​
}

Xamarin.Forms Exception System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation

I'm very new at Xamarin.Forms and I have one issue that I can't solve.
When I click on a button, it is supposed to navigate to page RegistracijaKorisnika.xaml (It is on Bosnian language .. sorry for that), but it does not because of the exception:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation
The page RegistracijaKorisnika.xaml has ViewModel page RegistracijaKorisnikaViewModel.cs and when i put in RegistracijaKorisnika.xaml.cs line :
BindingContext = new RegistracijaKorisnikaViewModel()
The exception occurs.
When I delete line
BindingContext = new RegistracijaKorisnikaViewModel()
I can navigate to the RegistracijaKorisnika.xaml.
Here is the code and I am hoping that you can help me.
This is RegistracijaKorisnika.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ITJobFinder.View.RegistracijaKorisnika">
<ContentPage.Content>
<StackLayout>
<Entry Placeholder="Ime" x:Name="entryImeKorisnika" Text="{Binding ImeKorisnika}"/>
<Entry Placeholder="Prezime" x:Name="entryPrezimeKorisnika" Text="{Binding PrezimeKorisnika}"/>
<Entry Placeholder="Email" x:Name="entryEmailKorisnika" Text="{Binding EmailKorisnika}"/>
<Entry Placeholder="Password" x:Name="entryPasswordKorisnika" Text="{Binding PasswordKorisnika}"/>
<Entry Placeholder="Naziv zavrsene obrazovne institucije" x:Name="entryNazivFakulteta" Text="{Binding NazivObrazovanjaKOrisnika}"/>
<Entry Placeholder="Godina zavrsetka obrazovanja" x:Name="entryGodinaZavrsetkaObrazovanja" Text="{Binding GodinaZavrsetkaObrazovanja}"/>
<Button Text="Registruj se!" Command="{Binding SaveNewUser}"/>
</StackLayout>
</ContentPage.Content>
</ContentPage>
This is RegistracijaKorisnika.xaml.cs
namespace ITJobFinder.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RegistracijaKorisnika : ContentPage
{
public RegistracijaKorisnika ()
{
InitializeComponent ();
BindingContext = new RegistracijaKorisnikaViewModel();
}
}
}
This is RegistracijaKorisnikaViewModel.cs
namespace ITJobFinder.ViewModel
{
public class RegistracijaKorisnikaViewModel : BaseViewModel
{
private string imeKorisnika;
private string prezimeKorisnika;
private string emailKorisnika;
private string passwordKorisnika;
private string nazivObrazovanjaKOrisnika;
private string godinaZavrsetkaObrazovanja;
public string ImeKorisnika
{
get => imeKorisnika;
set
{
imeKorisnika = value;
OnPropertyChanged();
}
}
public string PrezimeKorisnika
{
get => PrezimeKorisnika;
set
{
prezimeKorisnika = value;
OnPropertyChanged();
}
}
public string EmailKorisnika
{
get => emailKorisnika;
set
{
emailKorisnika = value;
OnPropertyChanged();
}
}
public string PasswordKorisnika
{
get => passwordKorisnika;
set
{
passwordKorisnika = value;
OnPropertyChanged();
}
}
public string NazivObrazovanjaKOrisnika
{
get => nazivObrazovanjaKOrisnika;
set
{
nazivObrazovanjaKOrisnika = value;
OnPropertyChanged();
}
}
public string GodinaZavrsetkaObrazovanja
{
get => godinaZavrsetkaObrazovanja;
set
{
godinaZavrsetkaObrazovanja = value;
OnPropertyChanged();
}
}
public ICommand SaveNewUser { get; private set; }
private DataBaseContext _context;
public RegistracijaKorisnikaViewModel()
{
_context = new DataBaseContext();
SaveNewUser = new Command(SaveUser);
}
void SaveUser()
{
Korisnik k = new Korisnik
{
ImeKorisnika = ImeKorisnika,
PrezimeKorisnika = PrezimeKorisnika,
EmailKorisnika = EmailKorisnika,
PasswordKorisnika = PasswordKorisnika,
GodinaZavrsetkaObrazovanja = GodinaZavrsetkaObrazovanja,
NazivObrazovanjaKOrisnika = NazivObrazovanjaKOrisnika
};
_context.Korisnici.Add(k);
_context.SaveChanges();
}
}
}
this get will cause an self-referential loop - your get should be using the lower-case internal variable, not the upper case Property name
public string PrezimeKorisnika
{
// should be "prezimeKorisnika"
get => PrezimeKorisnika;
set
{
prezimeKorisnika = value;
OnPropertyChanged();
}
}