Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makale , IWidgetProvider arabirimini uygulayan basit bir pencere öğesi sağlayıcısı oluşturma işleminde size yol gösterir. Bu arabirimin yöntemleri, pencere öğesini tanımlayan verileri istemek veya pencere öğesi sağlayıcısının bir pencere öğesindeki kullanıcı eylemine yanıt vermesini sağlamak için pencere öğesi konağı tarafından çağrılır. Pencere öğesi sağlayıcıları tek bir pencere öğesini veya birden çok pencere öğesini destekleyebilir. Bu örnekte iki farklı pencere öğesi tanımlayacağız. Uyarlamalı Kartlar çerçevesi tarafından sağlanan biçimlendirme seçeneklerinden bazılarını gösteren bir örnek hava durumu widget'ıdır. İkinci pencere öğesi, kullanıcı pencere öğesinde görüntülenen bir düğmeye her tıkladığınızda artan bir sayaç tutarak kullanıcı eylemlerini ve özel pencere öğesi durumu özelliğini gösterir.
Bu makaledeki bu örnek kod, Windows Uygulama SDK'sı Pencere Öğeleri Örneği uyarlanmıştır. C++/WinRT kullanarak pencere öğesi sağlayıcısı uygulamak için bkz. Win32 uygulamasında pencere öğesi sağlayıcısı uygulama (C++/WinRT).
Önkoşullar
- Test için kullanılabilen Widget Panosu'na sahip bir Windows 11 cihazı.
- Cihazınızda geliştirici modu etkinleştirilmiş olmalıdır. Daha fazla bilgi için bkz. Geliştiriciler için ayarlar.
- WinUI uygulama geliştirme iş yüküyle Visual Studio 2022 veya üzeri.
Yeni bir C# konsol uygulaması oluşturma
Visual Studio'da yeni bir proje oluşturun. Yeni proje oluştur iletişim kutusunda dil filtresini "C#" ve platform filtresini Windows olarak ayarlayın ve konsol uygulaması proje şablonunu seçin. Yeni projeyi "ExampleWidgetProvider" olarak adlandırın. İstendiğinde hedef .NET sürümünü 8.0 olarak ayarlayın.
Proje yüklendiğinde,
project .NET 8.0'ı destekleyecek şekilde güncelleştirmek için
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
Bu kılavuzda, kolay hata ayıklamayı etkinleştirmek için pencere öğesi etkinleştirildiğinde konsol penceresini görüntüleyen bir konsol uygulaması kullanıldığına dikkat edin. Pencere öğesi sağlayıcısı uygulamanızı yayımlamaya hazır olduğunuzda, Konsol uygulamanızı Windows uygulamasına dönüştürme içindeki adımları izleyerek konsol uygulamasını bir Windows uygulamasına dönüştürebilirsiniz.
Windows Uygulama SDK'sı'ye referanslar ekleme
Bu kılavuzda Microsoft.WindowsAppSDK 2.5.1 kullanılır. Çözüm Gezgini'da Dependencies sağ tıklayın ve NuGet paketlerini yönet... öğesini seçin. . NuGet paket yöneticisinde Browse sekmesini seçin ve "Microsoft. WindowsAppSDK". 2.5.1 sürümünü veya Windows Uygulama SDK'sı yayın kanalları'ndan sonraki desteklenen kararlı bir sürümü seçin ve ardından Yükle'ye tıklayın. Uygulama ve paketleme projelerinde aynı paket sürümünü kullanın. Bu, pencere öğesi API'lerinin kullanıma sunulduğu en düşük sürüm değil, izlenecek yol tarafından kullanılan sürümdür.
Pencere öğesi işlemlerini yönetmek için bir WidgetProvider sınıfı ekleyin.
Visual Studio'da ExampleWidgetProvider projesine sağ tıklayın ve Add->Class öğesini seçin.
Sınıf Ekle iletişim kutusunda sınıfı "WidgetProvider" olarak adlandırın ve Ekledüğmesine tıklayın. Oluşturulan WidgetProvider.cs dosyasında sınıf tanımını , IWidgetProvider arabirimini uyguladığını gösterecek şekilde güncelleştirin.
// WidgetProvider.cs
internal class WidgetProvider : IWidgetProvider
Etkinleştirilmiş pencere öğelerini takip etmeye hazırlan
Pencere öğesi sağlayıcısı tek bir pencere öğesini veya birden çok pencere öğesini destekleyebilir. Pencere öğesi konağı, pencere öğesi sağlayıcısıyla bir işlem başlattığında, işlemle ilişkili pencere öğesini tanımlamak için bir kimlik numarası aktarır. Her pencere öğesinin, özel verileri depolamak için kullanılabilecek ilişkili bir adı ve durum değeri de vardır. Bu örnekte, sabitlenmiş her pencere öğesinin kimliğini, adını ve verilerini depolamak için basit bir yardımcı yapı bildireceğiz. Pencere öğeleri, aşağıdaki Etkinleştir ve Devre Dışı Bırak bölümünde açıklanan etkin bir durumda da olabilir ve boole değeri olan her pencere öğesi için bu durumu takip edeceğiz. Aşağıdaki tanımı WidgetProvider.cs dosyasına ExampleWidgetProvider ad alanının içine, ancak WidgetProvider sınıf tanımının dışına ekleyin.
// WidgetProvider.cs
public class CompactWidgetInfo
{
public string? widgetId { get; set; }
public string? widgetName { get; set; }
public int customState = 0;
public bool isActive = false;
}
WidgetProvider.cs dosyasındaki WidgetProvider sınıf tanımının içine, her girişin anahtarı olarak pencere öğesi kimliğini kullanarak etkin pencere öğelerinin listesini koruyacak bir dizin üyesi ekleyin.
// WidgetProvider.cs
// Class member of WidgetProvider
public static Dictionary<string, CompactWidgetInfo> RunningWidgets = new Dictionary<string, CompactWidgetInfo>();
Widget şablonu JSON dizelerini tanımlama
Bu örnekte, her pencere öğesi için JSON şablonlarını tanımlamak üzere bazı statik dizeler bildirilecektir. Kolaylık sağlamak için bu şablonlar WidgetProvider sınıfının üye değişkenlerinde depolanır. Şablonlar için genel bir depolama alanına ihtiyacınız varsa, bunlar uygulama paketinin bir parçası olarak eklenebilir: Paket Dosyalarına Erişme. Pencere öğesi şablonu JSON belgesi oluşturma hakkında bilgi için bkz. Uyarlamalı Kartlar Designer ile pencere öğesi şablonu oluşturma.
Windows pencere öğeleri uygulayan uygulamalar, üst bilgi özelleştirmeyi destekleyen konaklarda pencere öğesi için görüntülenen üst bilgiyi özelleştirebilir. Daha fazla bilgi için bkz. Pencere öğesi üst bilgisi alanını özelleştirme.
Uyarı
Web pencere öğesi, URL'den sunulan HTML'yi görüntüleyebilir. Sağlayıcı, bu URL'yi belirtmek için hala bir Uyarlamalı Kart JSON yükü sağlar ve hala IWidgetProvider uygular. Kaynak ve mesajlaşma API'leri Windows Uygulama SDK'sı 1.6.3'te kullanıma sunulmuştur. Kurulum ve konak gereksinimleri için bkz. Web widget sağlayıcıları.
// WidgetProvider.cs
// Class members of WidgetProvider
const string weatherWidgetTemplate = """
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.0",
"speak": "<s>The forecast for Seattle January 20 is mostly clear with a High of 51 degrees and Low of 40 degrees</s>",
"backgroundImage": "https://raw.githubusercontent.com/microsoft/AdaptiveCards/59402c8d43f7a69a68e0b4fccc08f8a76fc98ccd/source/nodejs/adaptivecards-site/themes/adaptivecards/source/content/Mostly%20Cloudy-Background.jpg",
"body": [
{
"type": "TextBlock",
"text": "Redmond, WA",
"size": "large",
"isSubtle": true,
"wrap": true
},
{
"type": "TextBlock",
"text": "Mon, Nov 4, 2019 6:21 PM",
"spacing": "none",
"wrap": true
},
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "Image",
"url": "https://raw.githubusercontent.com/microsoft/AdaptiveCards/59402c8d43f7a69a68e0b4fccc08f8a76fc98ccd/source/nodejs/adaptivecards-site/themes/adaptivecards/source/content/Mostly%20Cloudy-Square.png",
"size": "small",
"altText": "Mostly cloudy weather"
}
]
},
{
"type": "Column",
"width": "auto",
"items": [
{
"type": "TextBlock",
"text": "46",
"size": "extraLarge",
"spacing": "none",
"wrap": true
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "°F",
"weight": "bolder",
"spacing": "small",
"wrap": true
}
]
},
{
"type": "Column",
"width": "stretch",
"items": [
{
"type": "TextBlock",
"text": "Hi 50",
"horizontalAlignment": "left",
"wrap": true
},
{
"type": "TextBlock",
"text": "Lo 41",
"horizontalAlignment": "left",
"spacing": "none",
"wrap": true
}
]
}
]
}
]
}
""";
const string countWidgetTemplate = """
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"text": "You have clicked the button ${count} times"
},
{
"text":"Rendering Only if Small",
"type":"TextBlock",
"$when":"${$host.widgetSize==\"small\"}"
},
{
"text":"Rendering Only if Medium",
"type":"TextBlock",
"$when":"${$host.widgetSize==\"medium\"}"
},
{
"text":"Rendering Only if Large",
"type":"TextBlock",
"$when":"${$host.widgetSize==\"large\"}"
}
],
"actions": [
{
"type": "Action.Execute",
"title": "Increment",
"verb": "inc"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.5"
}
""";
IWidgetProvider yöntemlerini uygulama
Sonraki birkaç bölümde IWidgetProvider arabiriminin yöntemlerini uygulayacağız. Bu yöntem uygulamalarından birkaçında çağrılan yardımcı UpdateWidget yöntemi bu makalenin devamında gösterilecektir.
Uyarı
IWidgetProvider arabiriminin geri çağırma yöntemlerine geçirilen nesnelerin yalnızca geri çağırma içinde geçerli olacağı garanti edilir. Geri çağırma bağlamı dışındaki davranışları tanımsız olduğundan, bu nesnelere yönelik başvuruları depolamamalısınız.
WidgetOluştur
Kullanıcı, uygulamanızın pencere öğelerinden birini pencere öğesi konağına sabitlediğinde, pencere öğesi konağı CreateWidget çağırır. İlk olarak, bu yöntem ilişkili pencere öğesinin kimliğini ve adını alır ve etkin pencere öğelerinin koleksiyonuna yardımcı yapımız CompactWidgetInfo'nun yeni bir örneğini ekler. Ardından, UpdateWidget yardımcı yönteminde kapsüllenen pencere öğesi için ilk şablonu ve verileri gönderiyoruz.
// WidgetProvider.cs
public void CreateWidget(WidgetContext widgetContext)
{
var widgetId = widgetContext.Id; // To save RPC calls
var widgetName = widgetContext.DefinitionId;
CompactWidgetInfo runningWidgetInfo = new CompactWidgetInfo() { widgetId = widgetId, widgetName = widgetName };
RunningWidgets[widgetId] = runningWidgetInfo;
// Update the widget
UpdateWidget(runningWidgetInfo);
}
DeleteWidget
Kullanıcı uygulamanızın widget'larından birini widget konağından kaldırdığında, widget konağı DeleteWidget çağırır. Bu durumda, ilgili pencere öğesini etkin pencere öğeleri listemizden kaldıracağız, böylece bu pencere öğesi için başka güncelleştirme göndermeyeceğiz.
// WidgetProvider.cs
public void DeleteWidget(string widgetId, string customState)
{
RunningWidgets.Remove(widgetId);
if(RunningWidgets.Count == 0)
{
emptyWidgetListEvent.Set();
}
}
Bu örnekte, etkin pencere öğeleri listesinden belirtilen pencere öğesini kaldırmaya ek olarak, listenin artık boş olup olmadığını da denetleriz ve boşsa, etkin pencere öğesi olmadığında uygulamanın çıkışına izin vermek için daha sonra kullanılacak bir olay ayarlarız. Sınıf tanımınızın içine ManualResetEvent bildirimini ve genel erişimci işlevini ekleyin.
// WidgetProvider.cs
static ManualResetEvent emptyWidgetListEvent = new ManualResetEvent(false);
public static ManualResetEvent GetEmptyWidgetListEvent()
{
return emptyWidgetListEvent;
}
OnActionInvoked
Kullanıcı pencere öğesi şablonunuzda tanımladığınız bir eylemle etkileşime geçtiğinde pencere öğesi konağı OnActionInvoked öğesini çağırır. Bu örnekte kullanılan sayaç widget'ı için, widget'ın JSON şablonunda fiili değeri "inc" olan bir eylem tanımlandı. Pencere öğesi sağlayıcısı kodu, kullanıcı etkileşimine yanıt olarak hangi eylemin gerçekleştirileceğini belirlemek için bu fiili değerini kullanır.
...
"actions": [
{
"type": "Action.Execute",
"title": "Increment",
"verb": "inc"
}
],
...
OnActionInvoked yönteminde, yönteme geçirilen WidgetActionInvokedArgs'in Fiil özelliğini kontrol ederek fiil değerini alın. Fiil "inc" ise, pencere öğesi için özel durumdaki sayıyı artıracağımızı biliyoruz. WidgetActionInvokedArgs öğesinden, güncelleştirilmekte olan pencere öğesi örneğini tanımlamak için WidgetContext nesnesini ve ardından Id özelliğini alın. Etkinleştirilmiş pencere öğeleri haritamızda belirtilen ID'ye sahip girdiyi bulun ve ardından artış sayısını depolamak için kullanılan özel durum değerini güncelleyin. Son olarak, updateWidget yardımcı işleviyle pencere öğesi içeriğini yeni değerle güncelleştirin.
// WidgetProvider.cs
public void OnActionInvoked(WidgetActionInvokedArgs actionInvokedArgs)
{
var verb = actionInvokedArgs.Verb;
if (verb == "inc")
{
var widgetId = actionInvokedArgs.WidgetContext.Id;
// If you need to use some data that was passed in after
// Action was invoked, you can get it from the args:
var data = actionInvokedArgs.Data;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
// Increment the count
localWidgetInfo.customState++;
UpdateWidget(localWidgetInfo);
}
}
}
Uyarlamalı Kartlar için Action.Execute söz dizimi hakkında bilgi için bkz. Action.Execute. Pencere öğeleri için etkileşim tasarlama hakkında yönergeler için bkz. Pencere öğesi etkileşimi tasarım kılavuzu.
OnWidgetContextChanged
Geçerli sürümde , OnWidgetContextChanged yalnızca kullanıcı sabitlenmiş pencere öğesinin boyutunu değiştirdiğinde çağrılır. İstenen boyuta bağlı olarak pencere öğesi konağına farklı bir JSON şablonu/verisi döndürmeyi seçebilirsiniz. Ayrıca , host.widgetSize değerini temel alan koşullu işlemeyi kullanarak kullanılabilir tüm boyutları desteklemek için JSON şablonunu tasarlayabilirsiniz. Boyut değişikliğini hesaba eklemek için yeni bir şablon veya veri göndermeniz gerekmiyorsa telemetri amacıyla OnWidgetContextChanged kullanabilirsiniz.
// WidgetProvider.cs
public void OnWidgetContextChanged(WidgetContextChangedArgs contextChangedArgs)
{
var widgetContext = contextChangedArgs.WidgetContext;
var widgetId = widgetContext.Id;
var widgetSize = widgetContext.Size;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
UpdateWidget(localWidgetInfo);
}
}
Etkinleştirme ve Devre Dışı Bırakma
Activate yöntemi, widget sağlayıcısına widget ana bilgisayarının sağlayıcıdan güncelleştirilmiş içerik almakla ilgilendiğini bildirmek için çağrılır. Örneğin, kullanıcının şu anda widget barındırıcısını aktif bir şekilde görüntülediği anlamına gelebilir. Deactivate yöntemi, widget sağlayıcısına artık widget barındırıcısının içerik güncelleştirmeleri istemediğini bildirmek için çağrılır. Bu iki yöntem, pencere öğesi ana bilgisayarının en çok up-totarih içeriğini göstermekle ilgilendiği bir pencere tanımlar. Pencere öğesi sağlayıcıları, herhangi bir zamanda, örneğin bir push bildirimine yanıt olarak pencere öğesine güncelleme gönderebilir, ancak herhangi bir arka plan görevinde olduğu gibi, pil ömrü gibi kaynak endişeleriyle güncel içerik sağlamayı dengelemek önemlidir.
etkinleştir ve devre dışı bırak widget başına çağrılır. Bu örnek , CompactWidgetInfo yardımcı yapısındaki her pencere öğesinin etkin durumunu izler. Activate yönteminde, pencere öğesimizi güncelleştirmek için UpdateWidget yardımcı yöntemini çağırırız. Etkinleştir ve Devre Dışı Bırak arasındaki zaman penceresinin küçük olabileceğini unutmayın; bu nedenle pencere öğesinizin kod yolunu olabildiğince hızlı güncelleştirmesini sağlamanız önerilir.
// WidgetProvider.cs
public void Activate(WidgetContext widgetContext)
{
var widgetId = widgetContext.Id;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
localWidgetInfo.isActive = true;
UpdateWidget(localWidgetInfo);
}
}
public void Deactivate(string widgetId)
{
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
localWidgetInfo.isActive = false;
}
}
Widget güncelle
Etkin bir pencere öğesini güncelleştirmek için UpdateWidget yardımcı yöntemini tanımlayın. Bu örnekte, yöntemine geçirilen CompactWidgetInfo yardımcı yapısındaki pencere öğesinin adını denetleyeceğiz ve ardından hangi pencere öğesinin güncelleştirildiği temelinde uygun şablonu ve veri JSON'unu ayarlayacağız. WidgetUpdateRequestOptions, güncellenmekte olan widget için şablon, veri ve özel durumu ile başlatılır. WidgetManager sınıfının bir örneğini almak için WidgetManager::GetDefault öğesini çağırın ve ardından güncelleştirilmiş pencere öğesi verilerini pencere öğesi konağına göndermek için UpdateWidget'i çağırın.
// WidgetProvider.cs
void UpdateWidget(CompactWidgetInfo localWidgetInfo)
{
WidgetUpdateRequestOptions updateOptions = new WidgetUpdateRequestOptions(localWidgetInfo.widgetId);
string? templateJson = null;
if (localWidgetInfo.widgetName == "Weather_Widget")
{
templateJson = weatherWidgetTemplate.ToString();
}
else if (localWidgetInfo.widgetName == "Counting_Widget")
{
templateJson = countWidgetTemplate.ToString();
}
string? dataJson = null;
if (localWidgetInfo.widgetName == "Weather_Widget")
{
dataJson = "{}";
}
else if (localWidgetInfo.widgetName == "Counting_Widget")
{
dataJson = "{ \"count\": " + localWidgetInfo.customState.ToString() + " }";
}
updateOptions.Template = templateJson;
updateOptions.Data = dataJson;
updateOptions.IsPlaceholderContent = localWidgetInfo.widgetName == "Weather_Widget";
// You can store some custom state in the widget service that you will be able to query at any time.
updateOptions.CustomState= localWidgetInfo.customState.ToString();
WidgetManager.GetDefault().UpdateWidget(updateOptions);
}
Henüz kişiselleştirilmemiş veya işlem yapılabilir olmayan içerik için WidgetUpdateRequestOptions.IsPlaceholderContent değerini true değerine ayarlayın. Sahte hava durumu pencere öğesi sabit bir konum görüntüler, bu nedenle bu örnek bunu yer tutucu içerik olarak işaretler. Ana makine, bu örnek hava durumu pencere öğesi yerine özelleştirilmiş içeriğe sahip pencere öğelerine öncelik verebilir. Kişiselleştirilmiş içerik sağladığınızda özelliği false olarak ayarlayın. Bu özellik Windows Uygulama SDK'sı 1.6.6'ya eklendi.
Uygulama başlangıcında etkin pencere öğelerinin listesini başlatın.
Pencere öğesi sağlayıcımız ilk başlatıldığında, sağlayıcımızın şu anda hizmet vermekte olduğu çalışan pencere öğeleri olup olmadığını WidgetManager'a sormak iyi bir fikirdir. Bilgisayarın yeniden başlatılması veya sağlayıcının çökmesi durumunda uygulamayı önceki durumuna geri getirmeye yardımcı olacaktır. Uygulamanın varsayılan pencere öğesi yöneticisi örneğini almak için WidgetManager.GetDefault'u çağırın. Ardından, bir dizi WidgetInfo nesnesi döndüren GetWidgetInfosçağrısını yapın. Pencere öğesi kimliklerini, adlarını ve özel durumunu CompactWidgetInfo yardımcı yapısına kopyalayın ve RunningWidgets üye değişkenine kaydedin. Aşağıdaki kodu WidgetProvider sınıfının sınıf tanımına yapıştırın.
// WidgetProvider.cs
public WidgetProvider()
{
var runningWidgets = WidgetManager.GetDefault().GetWidgetInfos();
foreach (var widgetInfo in runningWidgets)
{
var widgetContext = widgetInfo.WidgetContext;
var widgetId = widgetContext.Id;
var widgetName = widgetContext.DefinitionId;
var customState = widgetInfo.CustomState;
if (!RunningWidgets.ContainsKey(widgetId))
{
CompactWidgetInfo runningWidgetInfo = new CompactWidgetInfo() { widgetId = widgetId, widgetName = widgetName };
if (!string.IsNullOrEmpty(customState))
{
if (int.TryParse(customState, out int count))
{
runningWidgetInfo.customState = count;
}
else
{
Console.Error.WriteLine($"Invalid saved count for widget {widgetId}; resetting to 0.");
}
}
RunningWidgets[widgetId] = runningWidgetInfo;
}
}
}
İstek üzerine WidgetProvider örneği oluşturacak bir sınıf fabrikası uygulayın
Pencere öğesi ana bilgisayarının pencere öğesi sağlayıcımızla iletişim kurabilmesi için CoRegisterClassObjectçağrısı yapmamız gerekir. Bu işlev, WidgetProvider sınıfımız için bir sınıf nesnesi oluşturacak IClassFactory uygulamasını oluşturmamızı gerektirir. Sınıf fabrikamızı bağımsız bir yardımcı sınıfında uygulayacağız.
Visual Studio'da ExampleWidgetProvider projesine sağ tıklayın ve Add->Class öğesini seçin. Sınıf ekle
FactoryHelper.cs dosyasının içeriğini aşağıdaki kodla değiştirin. Bu kod , IClassFactory arabirimini tanımlar ve CreateInstance ve LockServer adlı iki yöntemini uygular. Bu kod, sınıf fabrikası uygulamak için tipik bir şablon koddur ve oluşturulan sınıf nesnesinin IWidgetProvider arabirimini uyguladığını belirtmemiz dışında bir araç sağlayıcısının işlevselliğine özgü değildir.
// FactoryHelper.cs
using Microsoft.Windows.Widgets.Providers;
using System.Runtime.InteropServices;
using WinRT;
namespace COM
{
static class Guids
{
public const string IClassFactory = "00000001-0000-0000-C000-000000000046";
public const string IUnknown = "00000000-0000-0000-C000-000000000046";
}
///
/// IClassFactory declaration
///
[ComImport, ComVisible(false), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(COM.Guids.IClassFactory)]
internal interface IClassFactory
{
[PreserveSig]
int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject);
[PreserveSig]
int LockServer(bool fLock);
}
[ComVisible(true)]
class WidgetProviderFactory<T> : IClassFactory
where T : IWidgetProvider, new()
{
public int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject)
{
ppvObject = IntPtr.Zero;
if (pUnkOuter != IntPtr.Zero)
{
return CLASS_E_NOAGGREGATION;
}
IntPtr provider = IntPtr.Zero;
try
{
provider = MarshalInspectable<IWidgetProvider>.FromManaged(new T());
return Marshal.QueryInterface(provider, in riid, out ppvObject);
}
catch (Exception exception)
{
Console.Error.WriteLine(exception);
return Marshal.GetHRForException(exception);
}
finally
{
if (provider != IntPtr.Zero)
{
Marshal.Release(provider);
}
}
}
int IClassFactory.LockServer(bool fLock)
{
return 0;
}
private const int CLASS_E_NOAGGREGATION = -2147221232;
}
}
Pencere öğesi sağlayıcınız için CLSID'yi temsil eden bir GUID oluşturun.
Ardından, COM etkinleştirmesi için pencere öğesi sağlayıcınızı tanımlamak için kullanılacak CLSID'yi temsil eden bir GUID oluşturmanız gerekir. Uygulamanızı paketlerken de aynı değer kullanılır. Tools-> GUID oluştur'a giderek Visual Studio'da GUID oluşturun. Kayıt defteri biçimi seçeneğini belirleyin ve Kopyala'ya tıklayın ve daha sonra kopyalayabilmeniz için bunu bir metin dosyasına yapıştırın.
OLE ile pencere öğesi sağlayıcısı sınıf nesnesini kaydetme
Yürütülebilir dosyamızın Program.cs dosyasında, pencere öğesi sağlayıcımızı OLE'ye kaydetmek için CoRegisterClassObject'i çağıracağız, böylece pencere öğesi konağı onunla etkileşim kurabilir. Program.cs içeriğini aşağıdaki kodla değiştirin. Bu kod CoRegisterClassObject işlevini içeri aktarır ve önceki adımda tanımladığımız WidgetProviderFactory arabirimini geçirerek bu işlevi çağırır. önceki adımda oluşturduğunuz GUID'yi kullanmak için CLSID_Factory değişken bildirimini güncelleştirdiğinizden emin olun.
// Program.cs
using System.Runtime.InteropServices;
using ComTypes = System.Runtime.InteropServices.ComTypes;
using Microsoft.Windows.Widgets;
using ExampleWidgetProvider;
using COM;
using System;
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
[DllImport("ole32.dll")]
static extern int CoRegisterClassObject(
[MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnk,
uint dwClsContext,
uint flags,
out uint lpdwRegister);
[DllImport("ole32.dll")] static extern int CoRevokeClassObject(uint dwRegister);
WinRT.ComWrappersSupport.InitializeComWrappers();
Guid CLSID_Factory = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
var factory = new WidgetProviderFactory<WidgetProvider>();
Marshal.ThrowExceptionForHR(
CoRegisterClassObject(CLSID_Factory, factory, 0x4, 0x1, out uint cookie));
try
{
if (GetConsoleWindow() != IntPtr.Zero)
{
Console.WriteLine("Registered successfully. Press ENTER to exit.");
Console.ReadLine();
}
else
{
WidgetProvider.GetEmptyWidgetListEvent().WaitOne();
}
}
finally
{
int revokeResult = CoRevokeClassObject(cookie);
if (revokeResult < 0)
{
System.Diagnostics.Trace.TraceError($"CoRevokeClassObject failed: 0x{revokeResult:X8}");
}
GC.KeepAlive(factory);
}
Bu kod örneğinin, uygulamanın konsol uygulaması olarak çalışıp çalışmadığını belirlemek için GetConsoleWindow işlevini kullandığını ve bunun bu kılavuzun varsayılan davranışı olduğunu unutmayın. İşlev geçerli bir işaretçi döndürürse, konsola hata ayıklama bilgileri yazarız. Aksi takdirde, uygulama bir Windows uygulaması olarak çalışır. Bu durumda, etkin pencere öğeleri listesi boş olduğunda DeleteWidget yönteminde ayarladığımız olayı bekler ve ardından uygulamadan çıkarız. Örnek konsol uygulamasını Windows uygulamasına dönüştürme hakkında bilgi için bkz. Konsol uygulamanızı Windows uygulamasına dönüştürme.
Uyarı
Son widget'ın silinmesini beklemek, bu örnek için basitleştirilmiş bir yaşam süresi ilkesidir, IWidgetProvider gereksinimi değildir. Ana bilgisayar, pencere öğeleri sabitlenmiş durumdayken bir sağlayıcıyı etkinleştirebilir ve serbest bırakabilir. Bir üretim sağlayıcısında COM sunucusunun ömrünü bağımsız olarak yönetin, başlangıçta kaydedilmiş pencere öğesi durumunu geri yükleyin ve geri çağırmalar eşzamanlı olarak çalıştırılırsa paylaşılan duruma erişimi eşitleyin. Bkz. IWidgetProvider açıklamaları.
Pencere öğesi sağlayıcı uygulamanızı paketleyin
Bu kılavuz, masaüstü araç takımı sağlayıcısını bir MSIX paket bildirimi aracılığıyla kaydeder ve Windows Uygulama SDK'sı çalışma zamanının çerçeveye bağımlı dağıtımını kullanır. Aşağıdaki adımlar uygulamanızı paketleyip sağlayıcı bileşenini kaydeder. Bunun yerine bağımsız dağıtımı seçerseniz, Windows Application Packaging Project kullanırken her iki projenin ayarları da dahil olmak üzere Bağımsız uygulamaları dağıtma konusunu izleyin.
MSIX paketleme projesi oluşturma
Paketleme projesine Windows Uygulama SDK'sı paket referansı ekleyin
MSIX paketleme projesine Windows Uygulama SDK'sı nuget paketine bir başvuru eklemeniz gerekir. Çözüm Gezgini'da ExampleWidgetProviderPackage projesine çift tıklayarak ExampleWidgetProviderPackage.wapproj dosyasını açın. aşağıdaki xml dosyasını Project öğesinin içine ekleyin.
<!--ExampleWidgetProviderPackage.wapproj-->
<ItemGroup>
<PackageReference Include="Microsoft.WindowsAppSDK" Version="2.5.1">
<IncludeAssets>build</IncludeAssets>
</PackageReference>
</ItemGroup>
Uyarı
Kod parçacığı, pencere öğesi API'lerini tanıtan asgari sürümü değil 2.5.1 sürümünü kullanır. Önceki adımda desteklenen daha sonraki bir kararlı sürümü seçtiyseniz, Sürüm değerini bu sürümle eşleşecek şekilde güncelleştirin.
Paket bildirimini güncelleştirme
<!-- Package.appmanifest -->
<Package
...
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
Application öğesinin içinde Extensions adlı yeni bir boş öğe oluşturun. Bunun uap:VisualElementskapanış etiketinden sonra geldiğinden emin olun.
<!-- Package.appxmanifest -->
<Application>
...
<Extensions>
</Extensions>
</Application>
Eklememiz gereken ilk uzantı ComServer uzantısıdır. Bu işlem yürütülebilir dosyanın giriş noktasını işletim sistemine kaydeder. Bu uzantı, bir kayıt defteri anahtarı ayarlayarak COM sunucusunu kaydetmenin paketlenmiş uygulama eşdeğeridir ve pencere öğesi sağlayıcılarına özgü değildir. Aşağıdaki com:Extension öğesini Extensions öğesinin alt öğesi olarak ekleyin. com:Class öğesinin Id özniteliğindeki GUID değerini önceki adımda oluşturduğunuz GUID ile değiştirin.
<!-- Package.appxmanifest -->
<Extensions>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:ExeServer Executable="ExampleWidgetProvider\ExampleWidgetProvider.exe" DisplayName="ExampleWidgetProvider">
<com:Class Id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" DisplayName="ExampleWidgetProvider" />
</com:ExeServer>
</com:ComServer>
</com:Extension>
</Extensions>
Ardından, uygulamayı pencere öğesi sağlayıcısı olarak kaydeden uzantıyı ekleyin. uap3:Extension öğesini aşağıdaki kod parçacığına Extensions öğesinin alt öğesi olarak yapıştırın. COM öğesinin ClassId özniteliğini önceki adımlarda kullandığınız GUID ile değiştirdiğinizden emin olun.
<!-- Package.appxmanifest -->
<Extensions>
...
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.widgets" DisplayName="WidgetTestApp" Id="ContosoWidgetApp" PublicFolder="Public">
<uap3:Properties>
<WidgetProvider>
<ProviderIcons>
<Icon Path="Images\StoreLogo.png" />
</ProviderIcons>
<Activation>
<!-- Apps exports COM interface which implements IWidgetProvider -->
<CreateInstance ClassId="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" />
</Activation>
<TrustedPackageFamilyNames>
<TrustedPackageFamilyName>Microsoft.MicrosoftEdge.Stable_8wekyb3d8bbwe</TrustedPackageFamilyName>
</TrustedPackageFamilyNames>
<Definitions>
<Definition Id="Weather_Widget"
DisplayName="Weather Widget"
Description="Weather Widget Description"
AllowMultiple="true">
<Capabilities>
<Capability>
<Size Name="small" />
</Capability>
<Capability>
<Size Name="medium" />
</Capability>
<Capability>
<Size Name="large" />
</Capability>
</Capabilities>
<ThemeResources>
<Icons>
<Icon Path="ProviderAssets\Weather_Icon.png" />
</Icons>
<Screenshots>
<Screenshot Path="ProviderAssets\Weather_Screenshot.png" DisplayAltText="For accessibility" />
</Screenshots>
<!-- DarkMode and LightMode are optional -->
<DarkMode />
<LightMode />
</ThemeResources>
</Definition>
<Definition Id="Counting_Widget"
DisplayName="Microsoft Counting Widget"
Description="Counting Widget Description">
<Capabilities>
<Capability>
<Size Name="small" />
</Capability>
</Capabilities>
<ThemeResources>
<Icons>
<Icon Path="ProviderAssets\Counting_Icon.png" />
</Icons>
<Screenshots>
<Screenshot Path="ProviderAssets\Counting_Screenshot.png" DisplayAltText="For accessibility" />
</Screenshots>
<!-- DarkMode and LightMode are optional -->
<DarkMode>
</DarkMode>
<LightMode />
</ThemeResources>
</Definition>
</Definitions>
</WidgetProvider>
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
</Extensions>
Bu öğelerin tümüne ilişkin ayrıntılı açıklamalar ve biçim bilgileri için Pencere Öğesi Sağlayıcı Paketi Manifesto XML Biçimi'ne bakın.
Paketleme projenize simgeler ve diğer görüntüler ekleme
Çözüm Gezgini'da ExampleWidgetProviderPackage öğesine sağ tıklayın ve Add->Yeni Klasör öğesini seçin. Bu klasöre, önceki adımda Package.appxmanifest'de kullanılan ad olan ProviderAssets adını verin. Pencere öğelerimiz için Simgeleri ve Ekran Görüntüleri burada depolayacağız. İstediğiniz Simgeleri ve Ekran Görüntülerini ekledikten sonra, görüntü adlarının
Ekran görüntülerinin tasarım gereksinimleri ve yerelleştirilmiş ekran görüntüleri için adlandırma kuralları hakkında bilgi için bkz. Pencere öğesi seçiciyle entegrasyon.
Widget sağlayıcınızı test etme
Çözüm Platformları açılan listesinden geliştirme makinenizle eşleşen mimariyi seçin, örneğin "x64". Çözüm Gezgini'da çözümünüze sağ tıklayın ve Çözümü Derle'yi seçin, ardından ExampleWidgetProviderPackage öğesine sağ tıklayın ve Dağıt'ı seçin. Windows 11’de Windows+W ile Bileşenler panosunu açın, pencere öğesi seçicisini açın, Hava Durumu Pencere Öğesi'ni bulun ve Microsoft Counting Widget. Bunları panoya ekleyin ve işlevlerini test edin. Seçici denetimleri ve yerleşimi, Windows ve Widget Panosu güncelleştirmelerine göre farklılık gösterebilir.
Uyarlamalı Kartlar Tasarımcısı Windows $host değerlerini sağlamaz, sağlayıcı geri çağrılarınızı çağırmaz veya Pencere Öğeleri Panosu'nun görüntülenen sınırlarını zorlamaz. Widgets Panosu'nda şu kontrolleri tamamlayın:
- Pencere öğesinin seçicide beklenen ad, simge, ekran görüntüsü ve açıklamayla göründüğünü onaylayın.
- Pencere öğesini sabitleyin ve ilk şablonunu ve verilerini doğrulayın.
- Paket manifestinde bildirilen her boyuta yeniden boyutlandırın. Her boyutta kırpılmış, gizli veya taşan içerik olup olmadığını denetleyin.
-
doğru olduğunda her
$host.isUserContextAuthenticatedişlemini test edin. Yanlış olduğunda desteklenmeyen eylemleri gizleyin ve uygun bir geri dönüş sağlayın; bu bağlamda yalnızca Action.OpenUrl desteklenir. - Sağlayıcı işlemini durdurun ve yeniden başlatın, ardından sabitlenen her widget'ın özel durumundan geri yüklendiğini onaylayın.
- Widget'in sabitlemesini kaldırın ve DeleteWidget çağrısının yapıldığını onaylayın.
Bu kılavuzda ayrı paketleme projesi yerine tek projeli MSIX kullanan CLI öncelikli C# projesi için, Package.appxmanifest öğesini sağlayıcı projesine yerleştirin, true öğesini EnableMsixTooling olarak ayarlayın ve geliştirme paketi oluşturup kaydetmek için Windows Uygulaması Geliştirme CLI'sini kullanın:
Important
Windows Uygulaması Geliştirme CLI'si şu anda public preview sürümündedir. Özellikler ve komutlar son sürümden önce değişebilir. Bu komutu kullanmadan önce yüklü sürümün winapp run --help çıktısını denetleyin.
winapp run ExampleWidgetProvider.csproj --configuration Release --arch x64 --no-launch
Bu komut, uygulamayı doğrudan başlatmadan paketi kaydeder. COM sunucusunu pencere öğesi konağı aracılığıyla etkinleştirmek için Pencere Öğeleri Panosu'nu açın.
Widget sağlayıcınızda hata ayıklama
Pencere öğelerinizi sabitledikten sonra Pencere Öğesi Platformu, pencere öğesi hakkında ilgili bilgileri almak ve göndermek için pencere öğesi sağlayıcısı uygulamanızı başlatır. Çalışan pencere öğesinde hata ayıklamak için, çalışan pencere öğesi sağlayıcısı uygulamasına bir hata ayıklayıcı ekleyebilir veya Visual Studio pencere öğesi sağlayıcısı işlemi başlatıldıktan sonra hata ayıklamayı otomatik olarak başlatacak şekilde ayarlayabilirsiniz.
Çalışan işleme eklemek için:
- Visual Studio'da Debug -> İşleme bağlan öğesine tıklayın.
- İşlemleri filtreleyin ve istediğiniz pencere öğesi sağlayıcısı uygulamasını bulun.
- Hata ayıklayıcısını ekleyin.
Hata ayıklayıcıyı başlangıçta başlatıldığında işleme otomatik olarak eklemek için:
- Visual Studio Debug -> Diğer Hata Ayıklama Hedefleri -> Yüklü Uygulama Paketinde Hata Ayıklama öğesine tıklayın.
- Paketleri filtreleyin ve istediğiniz pencere öğesi sağlayıcısı paketini bulun.
- Bunu seçin ve "Başlatmayın, ancak başlatıldığında kodumu hata ayıklayın" diyen kutuyu işaretleyin.
- Ekle'e tıklayın.
Konsol uygulamanızı Windows uygulamasına dönüştürme
Bu kılavuzda oluşturulan konsol uygulamasını bir Windows uygulamasına dönüştürmek için, Çözüm Gezgini içindeki ExampleWidgetProvider projesine sağ tıklayın ve Properties öğesini seçin. Uygulama->Genel altında Çıktı türü'nü "Konsol Uygulaması"ndan "Windows Uygulaması" olarak değiştirin.
Bir proje dosyası düzenlemesi için OutputType değerini WinExe olarak ayarlayın:
<OutputType>WinExe</OutputType>
Son kullanıcı deneyimini doğrulamadan veya yayımlamadan önce bunu yapın. Pencere öğesi konağı COM sunucusunu etkinleştirdiğinde konsol sağlayıcısı bir terminal penceresi açabilir.
Widget'i yayımlama
Pencere öğesinizi geliştirip test ettikten sonra, kullanıcıların pencere öğelerinizi cihazlarına yükleyebilmesi için uygulamanızı Microsoft Store yayımlayabilirsiniz. Bir uygulamayı yayımlamaya yönelik adım adım yönergeler için bkz. Uyunu Microsoft Store yayımlama.
Widget Mağaza Koleksiyonu
Uygulamanız Microsoft Store yayımlandıktan sonra, uygulamanızın kullanıcıların Windows Pencere Öğeleri özelliğine sahip uygulamaları bulmasına yardımcı olan Pencere Öğeleri Mağaza Koleksiyonu'na eklenmesini isteyebilirsiniz. İsteğinizi göndermek için bkz. Mağaza Koleksiyonueklemek için Pencere Öğesi bilgilerinizi gönderme.
Pencere öğesi özelleştirmesini uygulamak
Windows Uygulama SDK'sı 1.4 sürümünden itibaren pencere öğeleri kullanıcı özelleştirmesini destekleyebilir. Bu özellik uygulandığında, "Özelleştir pencere öğesi" seçeneği, "Pencere öğesini kaldır" seçeneğinin üstünde yer alan üç nokta menüsüne eklenir.
Aşağıdaki adımlarda pencere öğesi özelleştirme işlemi özetlenmiştir.
- Normal işlemde pencere öğesi sağlayıcısı, pencere öğesi konağından gelen isteklere şablon ve normal pencere öğesi deneyimi için veri yükleri ile yanıt verir.
- Kullanıcı üç noktalı menüdeki Özelleştir pencere öğesi düğmesine tıklar.
- Pencere öğesi, kullanıcının pencere öğesi özelleştirme deneyimini istediği belirtmek için pencere öğesi sağlayıcısında OnCustomizationRequested olayını tetikler.
- Pencere öğesi sağlayıcısı, pencere öğesinin özelleştirme modunda olduğunu belirtmek için bir iç bayrak ayarlar. Özelleştirme modundayken, pencere öğesi sağlayıcısı normal pencere öğesi kullanıcı arabirimi yerine pencere öğesi özelleştirme kullanıcı arabirimi için JSON şablonlarını gönderir.
- Özelleştirme modundayken, kullanıcı özelleştirme kullanıcı arabirimiyle etkileşim kurarken pencere öğesi sağlayıcısı OnActionInvoked olaylarını alır ve kullanıcının eylemlerine göre iç yapılandırmasını ve davranışını ayarlar.
- OnActionInvoked olayıyla ilişkili eylem uygulama tanımlı "özelleştirmeden çık" eylemi olduğunda, pencere öğesi sağlayıcısı artık özelleştirme modunda olmadığını belirtmek için iç bayrağını sıfırlar ve normal pencere öğesi deneyimi için görsel ve veri JSON şablonlarını göndermeye devam eder ve özelleştirme sırasında istenen değişiklikleri yansıtır. Kullanıcının uygulama tanımlı çıkış özelleştirme eylemine tıklamadan özelleştirme deneyimini kapatması mümkündür. Bu durumda, IWidgetProviderAnalytics.OnAnalyticsInfoReported tetiklenir ve WidgetAnalyticsInfoReportedArgs.AnalyticsJson bir interactionKind 'exitCustomization' değerine sahip olur.
- Pencere öğesi sağlayıcısı, değişikliklerin pencere öğesi sağlayıcısı çağrıları arasında korunması için özelleştirme seçeneklerini diskte veya bulutta korur.
Uyarı
Windows Uygulama SDK'sı kullanılarak oluşturulan pencere öğeleri için Windows Pencere Öğesi Panosunda, özelleştirme kartı gösterildikten sonra üç nokta menüsünün yanıt vermemeye başlamasına neden olan bilinen bir hata vardır.
Tipik Pencere Öğesi özelleştirme senaryolarında kullanıcı, pencere öğesinde hangi verilerin görüntüleneceğini seçer veya pencere öğesinin görsel sunumunu ayarlar. Kolaylık olması için, bu bölümdeki örnekte kullanıcının önceki adımlarda uygulanan sayım pencere öğesinin sayacını sıfırlamasına olanak tanıyan özelleştirme davranışı eklenecektir.
Uyarı
Pencere öğesi özelleştirmesi için Windows Uygulama SDK'sı 1.4 veya üzeri gerekir. Bu kılavuzda Microsoft.WindowsAppSDK sürüm 2.5.1 kullanılır.
Özelleştirme desteği bildirmek için paket bildirimini güncelleştirin
Pencere öğesi konağına pencere öğesinin özelleştirmeyi desteklediğini bildirmek için, pencere öğesinin Tanım öğesine IsCustomizable özniteliğini ekleyin ve true olarak ayarlayın.
...
<Definition Id="Counting_Widget"
DisplayName="Microsoft Counting Widget"
Description="CONFIG counting widget description"
IsCustomizable="true">
...
Bir pencere öğesinin özelleştirme modunda olduğunu izleme
Bu makaledeki örnek, etkin pencere öğelerimizin geçerli durumunu izlemek için CompactWidgetInfo yardımcı yapısını kullanır. Pencere öğesi sunucusunun normal pencere öğesi şablonu yerine özelleştirme JSON şablonumuzu göndermemizi beklediği zamanları izlemek için kullanılacak inCustomization alanını ekleyin.
// WidgetProvider.cs
public class CompactWidgetInfo
{
public string widgetId { get; set; }
public string widgetName { get; set; }
public int customState = 0;
public bool isActive = false;
public bool inCustomization = false;
}
IWidgetProvider2'yi Gerçekleştir
Pencere öğesi özelleştirme özelliği IWidgetProvider2 arabirimi aracılığıyla kullanıma sunulur. Bu arabirimi uygulamak için WidgetProvider sınıf tanımını güncelleştirin.
// WidgetProvider.cs
internal class WidgetProvider : IWidgetProvider, IWidgetProvider2
IWidgetProvider2 arabiriminin OnCustomizationRequested geri çağırması için bir uygulama ekleyin. Bu yöntem, kullandığımız diğer geri çağırmalarla aynı deseni kullanır. WidgetContext'ten özelleştirilecek pencere öğesinin kimliğini alır ve bu pencere öğesiyle ilişkili CompactWidgetInfo yardımcı yapısını bulur ve inCustomization alanını true olarak ayarlarız.
// WidgetProvider.cs
public void OnCustomizationRequested(WidgetCustomizationRequestedArgs customizationInvokedArgs)
{
var widgetId = customizationInvokedArgs.WidgetContext.Id;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
localWidgetInfo.inCustomization = true;
UpdateWidget(localWidgetInfo);
}
}
Şimdi, pencere öğesi özelleştirme kullanıcı arabirimi için JSON şablonunu tanımlayan bir dize değişkeni bildirin. Bu örnekte, sağlayıcımızın normal pencere öğesi davranışına dönmesi için sinyal veren bir "Sayacı sıfırla" düğmesi ve "Özelleştirmeden çık" düğmemiz vardır. Bu tanımı diğer şablon tanımlarının yanına yerleştirin.
// WidgetProvider.cs
const string countWidgetCustomizationTemplate = @"
{
""type"": ""AdaptiveCard"",
""actions"" : [
{
""type"": ""Action.Execute"",
""title"" : ""Reset counter"",
""verb"": ""reset""
},
{
""type"": ""Action.Execute"",
""title"": ""Exit customization"",
""verb"": ""exitCustomization""
}
],
""$schema"": ""http://adaptivecards.io/schemas/adaptive-card.json"",
""version"": ""1.5""
}";
UpdateWidget'te özelleştirme şablonu gönderme
Ardından, verilerimizi ve görsel JSON şablonlarımızı pencere öğesi konağına gönderen UpdateWidget yardımcı yöntemimizi güncelleştireceğiz. Sayım pencere öğesini güncelleştirirken inCustomization alanının değerine bağlı olarak normal pencere öğesi şablonunu veya özelleştirme şablonunu göndeririz. Kısa olması için bu kod parçacığında özelleştirmeyle ilgili olmayan kod atlanır.
// WidgetProvider.cs
void UpdateWidget(CompactWidgetInfo localWidgetInfo)
{
...
else if (localWidgetInfo.widgetName == "Counting_Widget")
{
if (!localWidgetInfo.inCustomization)
{
templateJson = countWidgetTemplate.ToString();
}
else
{
templateJson = countWidgetCustomizationTemplate.ToString();
}
}
...
updateOptions.Template = templateJson;
updateOptions.Data = dataJson;
// You can store some custom state in the widget service that you will be able to query at any time.
updateOptions.CustomState = localWidgetInfo.customState.ToString();
WidgetManager.GetDefault().UpdateWidget(updateOptions);
}
Özelleştirme eylemlerine yanıt verme
Kullanıcılar özelleştirme şablonumuzdaki girişlerle etkileşime geçtiğinde, kullanıcı normal pencere öğesi deneyimiyle etkileşime geçtiğinde olduğu gibi Aynı OnActionInvoked işleyicisini çağırır. Özelleştirmeyi desteklemek için özelleştirme JSON şablonumuzda "reset" ve "exitCustomization" fiillerini ararız. "Sayacı sıfırla" eylemi customState'i 0'a sıfırlar ve özelleştirmeden çıkar. "Özelleştirmeden çık" eylemi, sayacı sıfırlamadan çıkış yapar. Her ikisi de inCustomization değerini false olarak ayarlar, böylece UpdateWidget normal pencere öğesi şablonunu gönderir.
// WidgetProvider.cs
public void OnActionInvoked(WidgetActionInvokedArgs actionInvokedArgs)
{
var verb = actionInvokedArgs.Verb;
if (verb == "inc")
{
var widgetId = actionInvokedArgs.WidgetContext.Id;
// If you need to use some data that was passed in after
// Action was invoked, you can get it from the args:
var data = actionInvokedArgs.Data;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
// Increment the count
localWidgetInfo.customState++;
UpdateWidget(localWidgetInfo);
}
}
else if (verb == "reset")
{
var widgetId = actionInvokedArgs.WidgetContext.Id;
var data = actionInvokedArgs.Data;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
// Reset the count
localWidgetInfo.customState = 0;
localWidgetInfo.inCustomization = false;
UpdateWidget(localWidgetInfo);
}
}
else if (verb == "exitCustomization")
{
var widgetId = actionInvokedArgs.WidgetContext.Id;
var data = actionInvokedArgs.Data;
if (RunningWidgets.ContainsKey(widgetId))
{
var localWidgetInfo = RunningWidgets[widgetId];
// Stop sending the customization template
localWidgetInfo.inCustomization = false;
UpdateWidget(localWidgetInfo);
}
}
}
Şimdi pencere öğesinizi dağıtırken üç nokta menüsünde Pencere öğesini özelleştir düğmesini görmeniz gerekir. Özelleştir düğmesine tıkladığınızda özelleştirme şablonunuz görüntülenir.
Sayacı sıfırla düğmesine tıklayarak sayacı 0'a sıfırlayın. Pencere öğesinizin normal davranışına dönmek için Özelleştirmeden çık düğmesine tıklayın.
Windows developer