CompositionTarget.Rendering doesn't like my event handler in XAML - xaml

I'm converting a Windows Phone 7 app to Windows Store, so I'm moving over to Xaml. I have a method that runs at a certain point to update the data on the screen. It either assigns or removes an event handler delegate to the CompositionTarget.Rendering event. The message I get is No overload for 'OnCompositionTargetRendering' matches delegate 'System.EventHandler' '
Here's what I have:
private void CheckCompleted()
{
Color completeColor;
if (this.DecryptedText.ToString().ToUpper() == this.ThisPuzzle.QuoteText.ToUpper())
{
// We're done!!! ...
CompositionTarget.Rendering -= this.OnCompositionTargetRendering;// new EventHandler(this.OnCompositionTargetRendering);
...
}
else
{
...
CompositionTarget.Rendering += this.OnCompositionTargetRendering;// new EventHandler(this.OnCompositionTargetRendering);
...
}
}
protected void OnCompositionTargetRendering(object sender, EventArgs args)
{
this.DisplayTime();
if (ThisPuzzle != null)
{
foreach (UIElement thisElement in Letters.Children)
{
...
}
}
}

If you check the documentation CompositionTarget.Rendering is of type EventHandler<object> in Windows Store apps and not of type EventHandler as in Silverlight.
This means you need to change the signature of your event handler accordingly to:
protected void OnCompositionTargetRendering(object sender, object args)

Related

How can I detect when the XAML Slider is Completed?

In XAML I have the <Slider />. It has the ValueChanged event. This event fires with every change to Value. I need to detect when the value change is over. LostFocus, PointerReleased are not the correct event. How can I detect this?
XAML, WinRT, Windows8.1 and UWP:
PointerCaptureLost event should work for mouse / touch
KeyUp event for keyboard
You can create a new class and inherit from Slider. From there on, you can look for the Thumb control & listen for the events you want.
Something like this should work:
public class SliderValueChangeCompletedEventArgs : RoutedEventArgs
{
private readonly double _value;
public double Value { get { return _value; } }
public SliderValueChangeCompletedEventArgs(double value)
{
_value = value;
}
}
public delegate void SlideValueChangeCompletedEventHandler(object sender, SliderValueChangeCompletedEventArgs args);
public class ExtendedSlider : Slider
{
public event SlideValueChangeCompletedEventHandler ValueChangeCompleted;
private bool _dragging = false;
protected void OnValueChangeCompleted(double value)
{
if (ValueChangeCompleted != null)
{
ValueChangeCompleted(this, new SliderValueChangeCompletedEventArgs(value) );
}
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
var thumb = base.GetTemplateChild("HorizontalThumb") as Thumb;
if (thumb != null)
{
thumb.DragStarted += ThumbOnDragStarted;
thumb.DragCompleted += ThumbOnDragCompleted;
}
thumb = base.GetTemplateChild("VerticalThumb") as Thumb;
if (thumb != null)
{
thumb.DragStarted += ThumbOnDragStarted;
thumb.DragCompleted += ThumbOnDragCompleted;
}
}
private void ThumbOnDragCompleted(object sender, DragCompletedEventArgs e)
{
_dragging = false;
OnValueChangeCompleted(this.Value);
}
private void ThumbOnDragStarted(object sender, DragStartedEventArgs e)
{
_dragging = true;
}
protected override void OnValueChanged(double oldValue, double newValue)
{
base.OnValueChanged(oldValue, newValue);
if (!_dragging)
{
OnValueChangeCompleted(newValue);
}
}
}
You can use pair of bool values isValueChanged and (if possible change value without manipulation of pointer
) isPressed;
private void Slider_ValueChanged(object s, RangeBaseValueChangedEventArgs e) {
if (!isPressed) {
AcceptChanges();
} else {
isValueChanged = true;
}
}
Initialization code:
Window.Current.CoreWindow.PointerPressed += (e, a) => { isPressed = true; };
Window.Current.CoreWindow.PointerReleased += (e, a) => {
isPressed = false;
if (isValueChanged) AcceptChanges();
};
I had a similar issue using a Slider on Windows8/WinRT.
My problem was the following: I was reacting to the ValueChanged Event and performing a long lasting operation (writing asynchronously to a file) after each trigger. And thus running into a concurrent editing exception. In order to avoid this, I used a DispatcherTimer.
//Class member
private DispatcherTimer myDispatcherTimer = null;
private void OnSliderValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
//I update my UI right away
...
//If the dispatcher is already created, stop it
if (myDispatcherTimer!= null)
myDispatcherTimer.Stop();
//Overwrite the DispatcherTimer and thus reset the countdown
myDispatcherTimer= new DispatcherTimer();
myDispatcherTimer.Tick += (sender, o) => DoSomethingAsync();
myDispatcherTimer.Interval = new TimeSpan(0,0,2);
myDispatcherTimer.Start();
}
private async void DoSomethingAsync()
{
await DoThatLongSaveOperation();
}
You cannot directly detect what the final value is, but you can at least delay the operation until there is a long pause between two updates (e.g. in my case, if the user drags the slider and stops while maintaining the drag for 2 seconds, the save operation will be fired anyway).

RoutedEventArgs and AllFramesEventArgs

I am trying to call a function whose parameters are object sender and RoutedEventsArg e. I need those parameters since I have created a button on the main window related to this function and when I click the button it links to my function.
protected void StartRecord(object sender,RoutedEventsArg e)
{
// some stuff that creates a button and then does stuff
}
In another function, I need to call the above function stated above, but this second function has a parameter of AllFramesReadyArg e, not RoutedEventsArg e. So how do i call out the first function
void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
this.StartRecord(sender, e);
// does not work since parameter calls for RoutedEventArgs
}
Your StartRecord is not part of the Kinect Toolbox. You appear to have written it and given it those two arguments. It doesn't need them, nor do you necessarily need the function.
You also do not want to be calling StartRecord in AllFramesReady. The AllFramesReady callback is fired every time all the frames are ready for processing (hence the function name), which happens roughly 30 times a second. You only need to tell it to record once.
Per your other question, StartRecord is a callback to a button -- it shouldn't be called in code. It is called when the user hits the associated button.
Just looking at the Kinect Toolbox code and the callbacks, your code should look something like this:
KinectRecorder _recorder;
File _outStream;
bool _isRecording = false;
private void KinectSetup()
{
// set up the Kinect here
_recorder = new KinectRecorder(KinectRecordOptions.Skeleton, _outStream);
// some other stuff to setup
}
private void sensor_AllFramesReady(object sender, AllFramesReadyEventArgs e)
{
SkeletonFrame skeleton;
if (_isRecording && skeleton != null)
{
_recorder.Record(skeleton);
}
}
public void StartRecord(object sender, RoutedEventsArg e)
{
_isRecording = !_isRecording;
}

What the right time for registering listener for Share/Search charms

I need to register different share charm listener for every page. I have 2 pages. I added following code in every one:
DataTransferManager.GetForCurrentView().DataRequested += App_DataRequested;
I added it in constructor of one page and in UserControl_Loaded event of another (first page just doesn't have UserControl_Loaded so why I added it directly to constructor). At the moment when second page tryting to load, I got exception:
WinRT information: An event handler has already been registered
Additional information: A method was called at an unexpected time.
Where should I place it and what is "right" time to do this??
Also it looks confusing that we have different DataTransferManager for every view, but only one is active at current time. Ever more, I noticed, if you add only one listener for first page, other pages will share this listener anyway. If I have only one shared listener for all pages, is it correct register it in app.xaml.cs?
The way I resolved this issue was to deregister the event in the onNavigatedfrom event as below:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested -= App_DataRequested;
base.OnNavigatedFrom(e);
}
In BasePage.cs in constructor I added
public BasePage()
{
if (!_isListenToDataRequested)
{
_isListenToDataRequested = true;
DataTransferManager manager = DataTransferManager.GetForCurrentView();
manager.DataRequested += AppDataRequested;
}
}
private async void AppDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
IShareable shareable = Frame.Content as IShareable;
if (shareable != null)
{
DataRequestDeferral deferral = args.Request.GetDeferral();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => shareable.AppDataRequested(sender, args));
deferral.Complete();
}
}
And all my pages look like
public sealed partial class ContentPage : IShareable
{
public void AppDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{...}
}
Another solution was run this as below
private DataTransferManager dataTransferManager;
Put this in page loaded event
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, new DispatchedHandler(() =>
{
this.dataTransferManager = DataTransferManager.GetForCurrentView();
this.dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>(this.OnDataRequested);
}));
And
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
// Unregister the current page as a share source.
this.dataTransferManager.DataRequested -=
new TypedEventHandler<DataTransferManager, DataRequestedEventArgs>
(this.OnDataRequested);
}
I'd suggest doing it in the navigating events, the OnNavigatingFrom event will be triggered before the OnNavigatingTo of the page you're going to so you won't have this problem.
protected override Task OnNavigatingTo(WinRTXamlToolkit.Controls.AlternativeNavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += dataTransfer_DataRequested;
return base.OnNavigatingTo(e);
}
protected override Task OnNavigatingFrom(WinRTXamlToolkit.Controls.AlternativeNavigatingCancelEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested -= dataTransfer_DataRequested;
return base.OnNavigatingFrom(e);
}
//Note: This is the WinRT Xaml Toolkit version of the events, but the standard events will work the same way.

defining event handler for Tick event of DispatcherTimer in windows 8 app

I am developing an application in windows 8 Visual studio 11, and I want to define an event handler for a DispatcherTimer instance as below:
public sealed partial class BlankPage : Page
{
int timecounter = 10;
DispatcherTimer timer = new DispatcherTimer();
public BlankPage()
{
this.InitializeComponent();
timer.Tick += new EventHandler(HandleTick);
}
private void HandleTick(object s,EventArgs e)
{
timecounter--;
if (timecounter ==0)
{
//disable all buttons here
}
}
.....
}
But I get the following Error :
Cannot implicitly convert type 'System.EventHandler' to 'System.EventHandler<object>'
I am a novice developer to widows 8 apps.
Would you please help me ?
almost had it :) You don't need to instantiate a new eventhandler object, you only need to point to the method that handles the event. Hence, an eventhandler.
int timecounter = 10;
DispatcherTimer timer = new DispatcherTimer();
public BlankPage()
{
this.InitializeComponent();
timer.Tick += timer_Tick;
}
protected void timer_Tick(object sender, object e)
{
timecounter--;
if (timecounter == 0)
{
//disable all buttons here
}
}
Try to read up on delegates to understand events Understanding events and event handlers in C#
Your code is expecting HandleTick to have two Object params. Not an object param and an EventArg param.
private void HandleTick(object s, object e)
NOT
private void HandleTick(object s,EventArgs e)
This is a change that took place for Windows 8.
WinRT makes use of Generics more than the standard .NET Runtime. DispatcherTimer.Tick as defined in WinRT is here:
public event EventHandler<object> Tick
While the WPF DispatcherTimer.Tick is here
public event EventHandler Tick
Also note that you don't have to use the standard named method to create an Event Handler. You can use a lambda to do it in place:
int timecounter = 10;
DispatcherTimer timer = new DispatcherTimer();
public BlankPage()
{
this.InitializeComponent();
timer.Tick += (s,o)=>
{
timecounter--;
if (timecounter == 0)
{
//disable all buttons here
}
};
}

Silverlight & events

namespace SilverlightApplication1
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
datePicker1.SelectedDateChanged -= datePicker1_SelectedDateChanged;
datePicker1.SelectedDate = DateTime.Today;
datePicker1.SelectedDateChanged += datePicker1_SelectedDateChanged;
}
private void datePicker1_SelectedDateChanged(object sender, SelectionChangedEventArgs e)
{
MessageBox.Show("datePicker1_SelectedDateChanged");
}
}
}
Why message box appears?
datePicker1.SelectedDateChanged -= datePicker1_SelectedDateChanged;
//Defines you use the RemoveHandler function. you might want to remove event handlers during the application lifetime
datePicker1.SelectedDate = DateTime.Today;
// You are Assigning to Datepicker Selected date
datePicker1.SelectedDateChanged += datePicker1_SelectedDateChanged;
// the event handlers on the relevant object are ready for user-initiated events at run time.
So The Message Box Came .
Third Line You Have Call The Eventhadler That Y it will come