poniedziałek, 28 września 2009

Pierwsze wrażenia z Microsoft Surface SDK 1.0 SP1

Kiedy w końcu udało mi się zdobyć dostęp do SDK Microsoft Surface, natchniony rozkminianiem o co w tym wszystkim chodzi, postanowiłem króciutko się podzielić pierwszymi doświadczeniami.

Instalacja

Instalacja oprócz tego że musiałem doinstalować coś do XNA przebiegła niezwykle sprawnie. Całość razem z SDK, przykładami, super emulatorem i resztą rzeczy o których jeszcze nie mam pojęcia, znalazły się bezboleśnie na moim dysku, a w Visual Studio doszły nowe typy projektów.

Development

Ci którzy może jeszcze nie słyszeli, na Surface-a robi się przede wszystkim w WPF i ponoć w XNA (nie sprawdziłem jeszcze). Różnica pomiędzy zwykłym WPFem, a WPFem na Surface polega na tym że mamy zestaw dodatkowych kontrolek

oraz tym że aplikację uruchamiamy w specjalnym emulatorze, zwanym "Surface Simulator".

Polecam zacząć swoją przygodę od przykładów zawartych w SDK, skąd nauczymy się najwięcej :)

Kursor myszki i touchpad z laptopa

Przykłady

Aby zwizualizować jak to wygląd w praktyce, nagrałem krótki filmik który niestety z powodu oporu przed nagrywaniem (winę ponosi "Surface Simulator"), nie oddaje pełnej frajdy z korzystania z tego dobrodziejstwa! Przez pełną frajdę rozumiem tu korzystanie z np. kilku myszek jednoczenie co symuluje palce użytkownika (patrz obrazki), czy też super dźwięk.

Na obrazku widać jak to jest zrobione w praktyce (mam dostępne 2 "palce" którymi obracam elementy, zmieniam ich wielkość itp.)


, a na filmie (jak wspomniałem trochę ograniczonym) widać jak to się wszystko uruchamia.



Jak tylko oderwę się na chwilę od tego cuda, postaram się wrzucić więcej info.

Pozdrawiam,

Jacek Ciereszko

poniedziałek, 21 września 2009

[Behaviors] TextBox Enter Button Invoke (TargetedTriggerAction)

Jakiś czas temu zdarzyło mi się napisać własny behavior, który w odróżnieniu od tych które dłubie na co dzień, może mieć zastosowanie w wielu aplikacjach, stąd też pomysł aby się nim podzielić :)

Co to są behaviorsy nie będę się rozpisywał w tym temacie. Zagadnienie jest większe, a do poczytania o nim polecam świetny artykuł: http://www.silverlightshow.net/items/Behaviors-and-Triggers-in-Silverlight-3.aspx

O co chodzi?

Skoro już wszyscy wiedzą co to są behaviorsy w Silverlight 3.0, to wypadało by powiedzieć że mój jest typu "TargetedTriggerAction", czyli wykonuje akcję na innym obiekcie gdy ten do którego jest przypisany, wywoła wybrany event.

Mój behavior po wciśnięciu przycisku "Enter" we wskazanym textboxsie zasymuluje wciśnięcie wskazanego przycisku (wszystko co dziedziczy z ButtonBase).

Pewnie pomyśleliście sobie od razu, co za bzdura, przecież można podpiąć event i wywołać tą samą metodę w kodzie. Tylko co w przypadku gdy namiętnie stosujemy MVVM, gdzie nasz "code behind" jest czyściutki i zawiera tylko konstruktor? W takim wypadku behavior jest tym czego poszukujemy. Co ważniejsze, "code behind" pozostaje nienaruszony, nie śmiecimy również w ViewModelu, a operacje "interfejsowe" pozostają ładnie oddzielone i nadają się do ponownego użycia.

Standardowe zastosowanie

Jak wspomniałem, behavior ma zastosowanie przede wszystkim w aplikacjach z wzorcem MVVM, a jego miejsce to np. pole wyszukiwania.

Live demo

Wciskając "Enter" w polu tekstowym otrzymujemy ten sam efekt co wciskając przycisk.

Dodajemy do aplikacji

    <Button x:Name="TargetedButton" Content="Targeted Button"  />
<TextBox Text="TextBox" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyDown" >
<behavior:TextBoxEnterButtonInvoke TargetName="TargetedButton" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>

, gdzie "i:" jest przestrzenią nazw dla "clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity", a "behavior:" dla projektu w którym umieszony jest kod bahaviora.

Kod źródłowy

Kodu jest niewiele, więc postanowiłem wkleić go cały.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.Windows.Controls.Primitives;

/// TargetedTriggerAction for TextBox control.
/// Invokes targeted button when Enter is pressed inside TextBox.
///
/// Jacek Ciereszko
/// http://jacekciereszko.pl
///

///

namespace TextBoxEnterBehavior
{
public class TextBoxEnterButtonInvoke : TargetedTriggerAction
{
///
/// Gets or sets the peer.
///

/// The peer.
private AutomationPeer _peer { get; set; }

///
/// Gets or sets the target button
///

private ButtonBase _targetedButton { get; set; }

///
/// Called after the TargetedTriggerAction is attached to an AssociatedObject.
///

/// Override this to hook up functionality to the AssociatedObject.
protected override void OnAttached()
{
base.OnAttached();
_targetedButton = this.Target;
if (null == _targetedButton)
{
return;
}

// set peer
this._peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (this._peer == null)
{
this._peer = FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}

///
/// Called after targeted Button change.
///

/// Override this to hook up functionality to the new targeted Button.
protected override void OnTargetChanged(ButtonBase oldTarget, ButtonBase newTarget)
{
base.OnTargetChanged(oldTarget, newTarget);
_targetedButton = newTarget;
if (null == _targetedButton)
{
return;
}

// set peer
this._peer = FrameworkElementAutomationPeer.FromElement(_targetedButton);
if (this._peer == null)
{
this._peer = FrameworkElementAutomationPeer.CreatePeerForElement(_targetedButton);
}
}

///
/// Invokes the targeted Button when Enter key is pressed inside TextBox.
///

/// KeyEventArgs with Enter key
protected override void Invoke(object parameter)
{
KeyEventArgs keyEventArgs = parameter as KeyEventArgs;
if (null != keyEventArgs && keyEventArgs.Key == Key.Enter)
{
if (null != _peer)
{
IInvokeProvider invokeProvider = _peer.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
invokeProvider.Invoke();
}
}
}
}
}

Do pobrania

Kod jest także dostępny do pobrania na stronie http://gallery.expression.microsoft.com/en-us/TextBoxInvokeButton.


Pozdrawiam,

Jacek Ciereszko