C++/winRT xaml Keyboard Event handler - c++-winrt

The following, when compiled, produces a "1 unresolved externals..."
My question is - what are the proper parameters?
using namespace winrt;
using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Input;
xaml
KeyDown="Keyboard_keyDown"
.h
void Keyboard_keyDown(Windows::Foundation::IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs e);
.cpp
void SettingsPage::Keyboard_keyDown(IInspectable const& sender,
Windows::UI::Xaml::Input::KeyRoutedEventArgs e) {...}
MainPage.xaml
<Page
x:Class="BlankAppKeypaderror.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:BlankAppKeypaderror"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
KeyDown="Keyboard_keyDown"
>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="myButton" Click="ClickHandler">Click Me</Button>
</StackPanel>
MainPage.h
pragma once
include "MainPage.g.h"
namespace winrt::DemoProblemApp::implementation {
struct MainPage : MainPageT
{
MainPage();
int32_t MyProperty();
void MyProperty(int32_t value);
void Keyboard_keyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs e);
void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);
}; }
namespace winrt::DemoProblemApp::factory_implementation {
struct MainPage : MainPageT
{
}; }
MainPage.cpp
#include "pch.h"
#include "MainPage.h"
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::DemoProblemApp::implementation {
MainPage::MainPage() {
InitializeComponent();
}
int32_t MainPage::MyProperty() {
throw hresult_not_implemented();
}
void MainPage::MyProperty(int32_t /* value */) {
throw hresult_not_implemented();
}
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&) {
myButton().Content(box_value(L"Clicked"));
}
void MainPage::Keyboard_keyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs e) {
}
}
I changed the handlers (,h & ,cpp) to the following and problem exists:
void Keyboard_KeyDown(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::Input::KeyRoutedEventArgs const& e);
2018-1207 - included this in the .h file
include

This was missing in the .H file
#include <winrt/Windows.UI.Xaml.Input.h>

Related

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.

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"));​
}

How to TwoWay bind a UserControl in UWP XAML? (C++/WinRT)

I am trying to two way bind data inside of a UserControl. The code below works for one way binding, but when I try to use two way binding I get the following error from the xaml compiler:
XamlCompiler error WMC1118: TwoWay binding target 'value_prop' must be a dependency property
However it's very confusing to me because I did make value_prop a dependency property. How can I make this work?
// MainPage.xaml
<local:attribute_slider Label="Scale" value_prop="{x:Bind texture_showcase_vm.current_texture.scale, Mode=TwoWay}"/>
// attribute_slider.xaml
<UserControl
x:Class="wzrd_editor.attribute_slider"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:wzrd_editor"
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" >
<TextBlock x:Name="scale_label" Text="{x:Bind Label, Mode=OneWay}" HorizontalAlignment="Left" />
<TextBlock x:Name="scale_text_value" Text="{x:Bind value_prop, Mode=TwoWay}" HorizontalAlignment="Right"
RelativePanel.AlignRightWithPanel="True"
RelativePanel.RightOf="scale_label" />
<Slider x:Name="Scale" Value="{x:Bind value_prop, Mode=TwoWay}" Width="200" Orientation="Horizontal" Minimum="0" Maximum="10" StepFrequency="0.01" TickFrequency="0.01" SnapsTo="StepValues" TickPlacement="None"
RelativePanel.Below="scale_label"
RelativePanel.AlignRightWith="scale_text_value"
RelativePanel.AlignLeftWith="scale_label"
RelativePanel.AlignRightWithPanel="True" />
</StackPanel>
</UserControl>
//attribute_slider.idl
namespace wzrd_editor
{
[bindable]
[default_interface]
runtimeclass attribute_slider : Windows.UI.Xaml.Controls.UserControl, Windows.UI.Xaml.Data.INotifyPropertyChanged
{
attribute_slider();
static Windows.UI.Xaml.DependencyProperty LabelProperty{ get; };
static Windows.UI.Xaml.DependencyProperty value_property{ get; set; };
String Label;
Single value_prop;
}
}
attribute_slider.h
namespace winrt::wzrd_editor::implementation
{
struct attribute_slider : attribute_sliderT<attribute_slider>
{
attribute_slider();
static Windows::UI::Xaml::DependencyProperty LabelProperty();
static Windows::UI::Xaml::DependencyProperty value_property();
static void value_property(Windows::UI::Xaml::DependencyProperty const& value);
hstring Label();
void Label(hstring const& value);
float value_prop();
void value_prop(float const& value);
winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
void PropertyChanged(winrt::event_token const& token) noexcept;
private:
static Windows::UI::Xaml::DependencyProperty m_labelProperty;
static Windows::UI::Xaml::DependencyProperty m_value_property;
hstring m_label = L"";
float m_value = 0.0f;
winrt::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));
}
template <class T>
void update_value(hstring const& property_name, T & var, T value)
{
if (var != value)
{
var = value;
raise_property_changed(property_name);
}
}
};
}
//attribute_slider.cpp
namespace winrt::wzrd_editor::implementation
{
Windows::UI::Xaml::DependencyProperty attribute_slider::m_labelProperty =
Windows::UI::Xaml::DependencyProperty::Register(
L"Label",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<wzrd_editor::attribute_slider>(),
Windows::UI::Xaml::PropertyMetadata{ nullptr }
);
Windows::UI::Xaml::DependencyProperty attribute_slider::m_value_property =
Windows::UI::Xaml::DependencyProperty::Register(
L"value_prop",
winrt::xaml_typename<winrt::hstring>(),
winrt::xaml_typename<wzrd_editor::attribute_slider>(),
Windows::UI::Xaml::PropertyMetadata{ nullptr }
);
attribute_slider::attribute_slider()
{
InitializeComponent();
}
hstring attribute_slider::Label()
{
return m_label;
}
void attribute_slider::Label(hstring const& value)
{
update_value(L"Label", m_label, value);
}
float attribute_slider::value_prop()
{
return m_value;
}
void attribute_slider::value_prop(float const& value)
{
update_value(L"value_prop", m_value, value);
}
Windows::UI::Xaml::DependencyProperty attribute_slider::LabelProperty()
{
return m_labelProperty;
}
Windows::UI::Xaml::DependencyProperty attribute_slider::value_property()
{
return m_value_property;
}
void attribute_slider::value_property(Windows::UI::Xaml::DependencyProperty const& value)
{
m_value_property = value;
}
winrt::event_token attribute_slider::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_property_changed.add(handler);
}
void attribute_slider::PropertyChanged(winrt::event_token const& token) noexcept
{
m_property_changed.remove(token);
}
}

Signature capture in Windows Phone 8.1

I'm surprised that I'm unable to find any solution for capturing signature in Windows Phone 8.1. So far I found only one in StackOverflow here... but it complains that WriteableBitmap.DrawLine method isn't available.
Code from the above link:
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
namespace ProofOfConcept.App.Controls
{
public class SignatureCaptureControl : Canvas
{
private WriteableBitmap _writeableBitmap;
private Point _currentPoint;
private Point _oldPoint;
public SignatureCaptureControl()
{
_writeableBitmap = new WriteableBitmap(300, 130);
PointerPressed += SignatureCaptureControl_PointerPressed;
PointerMoved += SignatureCaptureControl_PointerMoved;
}
private void SignatureCaptureControl_PointerPressed(object sender, PointerRoutedEventArgs e)
{
_currentPoint = e.GetCurrentPoint(this).Position;
_oldPoint = _currentPoint;
}
void SignatureCaptureControl_PointerMoved(object sender, PointerRoutedEventArgs e)
{
_currentPoint = e.GetCurrentPoint(this).Position;
_writeableBitmap.DrawLine((int)_currentPoint.X, (int)_currentPoint.Y, (int)_oldPoint.X, (int)_oldPoint.Y, PenColor);
this.InvalidateArrange();
_oldPoint = _currentPoint;
}
public void ClearSignature()
{
_writeableBitmap.Clear();
}
}
}
This code sample requires the WriteableBitmapEx library, the DrawLine method is defined as an extension method in that library.
You can install this package in NuGet package manager.
Finally I found a sample code that does exactly what I was looking for. It does let the user scribble their signature or whatever on the canvas, I'm yet to figure out how to save the image and upload it to a webservice. I'll get to that later. But here is the code to create a drawing pad.
Link to the website where I found the code.
I made it as a UserControl.
This is how I used the UserControl:
<Grid x:Name="inkPanel">
<Controls:SignatureCaptureControl/>
</Grid>
UserControl Xaml:
<UserControl
x:Class="MyApp.Controls.SignatureCaptureControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyApp.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="170"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="50"></RowDefinition>
</Grid.RowDefinitions>
<Canvas x:Name="inkCanvas" Grid.Row="0">
<Rectangle x:Name="rect" VerticalAlignment="Top" Height="150" Width="360" Fill="#FFF4F4F5" Stroke="Black" />
</Canvas>
<PasswordBox x:Name="txtPin" Grid.Row="1" Width="360" PlaceholderText="Enter Pin">
</PasswordBox>
<StackPanel Orientation="Horizontal" Grid.Row="2" Margin="0,10,0,0" HorizontalAlignment="Center">
<Button Name="btnAccept" Content="Accept" Click="btnAccept_Click"></Button>
<Button Name="btnClear" Content="Clear" Click="btnClear_Click"></Button>
</StackPanel>
</Grid>
</UserControl>
Code Behind:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
using Windows.UI;
// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236
namespace MyApp.Controls
{
public sealed partial class SignatureCaptureControl : UserControl
{
Windows.UI.Xaml.Shapes.Path _Current;
public SignatureCaptureControl()
{
this.InitializeComponent();
inkCanvas.PointerPressed += inkCanvas_PointerPressed;
inkCanvas.PointerMoved += inkCanvas_PointerMoved;
inkCanvas.PointerReleased += inkCanvas_PointerReleased;
inkCanvas.PointerExited += inkCanvas_PointerReleased;
}
void inkCanvas_PointerReleased(object sender, PointerRoutedEventArgs e)
{
_Current = null;
}
void inkCanvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
var pointer = e.GetCurrentPoint(inkCanvas);
if (!pointer.Properties.IsLeftButtonPressed || _Current == null)
return;
var segments = (_Current.Data as PathGeometry).Figures.First().Segments.First() as PolyLineSegment;
segments.Points.Add(pointer.Position);
}
void inkCanvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
var pointer = e.GetCurrentPoint(inkCanvas);
if (!pointer.Properties.IsLeftButtonPressed)
return;
_Current = new Windows.UI.Xaml.Shapes.Path
{
Data = new PathGeometry
{
Figures = { new PathFigure { StartPoint = pointer.Position, Segments = { new PolyLineSegment() } } }
},
Stroke = new SolidColorBrush(Colors.Black),
StrokeThickness = 4d,
};
inkCanvas.Children.Add(_Current);
}
private void btnClear_Click(object sender, RoutedEventArgs e)
{
inkCanvas.Children.Clear();
inkCanvas.Children.Add(rect);
txtPin.Password = "";
}
private void btnAccept_Click(object sender, RoutedEventArgs e)
{
}
}
}

Why Won't the Silverlight ChildWindow Display?

I have a simple Silverlight 4 application and have added a child window to it. I am using the below code to open it on a button click. This seems like it should work, does it not?
public void btnAbout_Click(object sender, RoutedEventArgs e)
{
About aboutThis = new About();
aboutThis.Show();
}
The "About" class looks like this:
public partial class About : ChildWindow
{
public About()
{
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
}
I don't see any reason why it should not work.
Samples:
http://www.tanguay.info/web/index.php?pg=codeExamples&id=135
http://www.silverlighttoys.com/Tutorials.aspx?tutorial=2
What is your XAML like?
Try setting the Width and Height to 600px by 600px of your About Childwindow from xaml.