Skip to content

Commit a8a8354

Browse files
authored
[Samples]: Add Windows Widgets C# Authoring sample (#275)
* add c# sample * Update WeatherWidget.cs * wait for disposing * clean up
1 parent 96aec14 commit a8a8354

30 files changed

+1054
-5
lines changed

Samples/Widgets/README.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,18 +30,20 @@ These samples demonstrate how to author Windows Widgets with the Windows App SDK
3030

3131
## WidgetProvider sample
3232

33-
This project includes a sample of a 3rd party widget provider. At this point, it's only possible to author widgets in C++ and Widget provider application must be a packaged application.
34-
33+
This project includes a sample of a 3rd party widget provider. The sample is a packaged application that is authored in both C++ and C#.
3534
## Converting sample from Console to Windows application
3635

3736
If the widget providing application doesn't have any UI - it's a good idea to convert the app to windows application so the console doesn't show to the end user.
3837
These are the required steps to convert the sample to windows application:
39-
- Right click on the SampleWidgetProviderApp in Visual Studio and open Properties. Navigate to Linker -> System and change SubSystem from Console to Windows. It can also be done by adding `<SubSystem>Windows</SubSystem>` to the `<Link>..</Link>` section of the .vcxproj.
40-
- Substitute `int main()` in `main.cpp` with `int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR pCmdLine, _In_ int /*nCmdShow*/)`.
38+
- For C++
39+
- Right click on the SampleWidgetProviderApp in Visual Studio and open Properties. Navigate to Linker -> System and change SubSystem from Console to Windows. It can also be done by adding `<SubSystem>Windows</SubSystem>` to the `<Link>..</Link>` section of the .vcxproj.
40+
- Substitute `int main()` in `main.cpp` with `int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR pCmdLine, _In_ int /*nCmdShow*/)`.
41+
- For C#
42+
- Right click on CsConsoleWidgetProvider in Visual Studio and open Properties. In the Output type dropdown choose `Windows Application`.
4143

4244
## Debugging WidgetProvider
4345

44-
After the solution has been built, you will need to deploy the `SampleWidgetProviderAppPackage`. In order to do that, right click on the `SampleWidgetProviderAppPackage` and click Deploy.
46+
After the solution has been built, you will need to deploy the `SampleWidgetProviderAppPackage(C++)` or `CsConsoleWidgetProvider(C#)`. In order to do that, right click on the desired project and click Deploy.
4547
Once you've done that, you may navigate to the Widgets Dashboard and pin your widget:
4648
- Open Widgets Dashboard by hovering over or clicking the widgets icon in the left bottom corner of the taskbar, or by using the shortcut `WIN + W`.
4749
- Click the `+` sign next to your user avatar.
432 Bytes
Loading
5.25 KB
Loading
1.71 KB
Loading
637 Bytes
Loading
283 Bytes
Loading
456 Bytes
Loading
2.05 KB
Loading
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using Microsoft.Windows.Widgets.Providers;
5+
using System;
6+
using System.Text.Json.Nodes;
7+
8+
namespace CsConsoleWidgetProvider
9+
{
10+
internal class CountingWidget : WidgetImplBase
11+
{
12+
public static string DefinitionId { get; } = "CSharp_Counting_Widget";
13+
public CountingWidget(string widgetId, string startingState) : base(widgetId, startingState)
14+
{
15+
if (state == string.Empty)
16+
{
17+
state = "0";
18+
}
19+
else
20+
{
21+
// This particular widget stores its clickCount in the state as integer.
22+
// Attempt to parse the saved state and convert it to integer.
23+
uint parsedClickCount;
24+
if (uint.TryParse(state, out parsedClickCount))
25+
{
26+
ClickCount = parsedClickCount;
27+
}
28+
}
29+
}
30+
31+
public override void OnActionInvoked(WidgetActionInvokedArgs actionInvokedArgs)
32+
{
33+
if (actionInvokedArgs.Verb == "inc")
34+
{
35+
ClickCount++;
36+
state = ClickCount.ToString();
37+
38+
var updateOptions = new WidgetUpdateRequestOptions(Id);
39+
updateOptions.Data = GetDataForWidget();
40+
updateOptions.CustomState = State;
41+
WidgetManager.GetDefault().UpdateWidget(updateOptions);
42+
}
43+
}
44+
45+
public override void OnWidgetContextChanged(WidgetContextChangedArgs contextChangedArgs)
46+
{
47+
// (Optional) There a several things that can be done here:
48+
// 1. If you need to adjust template/data for the new context (i.e. widget size has chaned) - you can do it here.
49+
// 2. Log this call for telemetry to monitor what size users choose the most.
50+
}
51+
52+
public override void Activate(WidgetContext widgetContext)
53+
{
54+
// Since this widget doesn't update data for any reason
55+
// except when 'Increment' button was clicked -
56+
// there's nothing to do here. However, for widgets that
57+
// constantly push updates this is the signal to start
58+
// pushing those updates since widget is now visible.
59+
isActivated = true;
60+
}
61+
62+
public override void Deactivate()
63+
{
64+
isActivated = false;
65+
}
66+
67+
private static string GetDefaultTemplate()
68+
{
69+
if (string.IsNullOrEmpty(WidgetTemplate))
70+
{
71+
// This widget has the same template for all the sizes/themes so we load it only once.
72+
WidgetTemplate = ReadPackageFileFromUri("ms-appx:///Templates/CountingWidgetTemplate.json");
73+
}
74+
75+
return WidgetTemplate;
76+
}
77+
78+
public override string GetTemplateForWidget()
79+
{
80+
return GetDefaultTemplate();
81+
}
82+
83+
public override string GetDataForWidget()
84+
{
85+
var stateNode = new JsonObject {
86+
["count"] = State
87+
};
88+
Console.WriteLine(stateNode.ToString());
89+
return stateNode.ToJsonString();
90+
}
91+
92+
private static string WidgetTemplate { get; set; } = "";
93+
94+
private uint ClickCount { get; set; }
95+
}
96+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<TargetFramework>net6.0-windows10.0.18362.0</TargetFramework>
5+
<TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion>
6+
<RootNamespace>CsConsoleWidgetProvider</RootNamespace>
7+
<Platforms>x86;x64;arm64</Platforms>
8+
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
9+
<UseWinUI>false</UseWinUI>
10+
<EnableMsixTooling>true</EnableMsixTooling>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<Content Include="Assets\SplashScreen.scale-200.png" />
15+
<Content Include="Assets\LockScreenLogo.scale-200.png" />
16+
<Content Include="Assets\Square150x150Logo.scale-200.png" />
17+
<Content Include="Assets\Square44x44Logo.scale-200.png" />
18+
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
19+
<Content Include="Assets\StoreLogo.png" />
20+
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
21+
<Content Include="ProviderAssets\**\*.png" />
22+
<Content Include="Templates\**\*.json" />
23+
</ItemGroup>
24+
25+
<ItemGroup>
26+
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.25231-preview" />
27+
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.2.221116.1" />
28+
</ItemGroup>
29+
30+
<!--
31+
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
32+
Tools extension to be activated for this project even if the Windows App SDK Nuget
33+
package has not yet been restored.
34+
-->
35+
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
36+
<ProjectCapability Include="Msix" />
37+
</ItemGroup>
38+
39+
<!--
40+
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
41+
Explorer "Package and Publish" context menu entry to be enabled for this project even if
42+
the Windows App SDK Nuget package has not yet been restored.
43+
-->
44+
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
45+
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
46+
</PropertyGroup>
47+
48+
<Import Project="..\WidgetHelper\WidgetHelper.projitems" Label="Shared" />
49+
</Project>

0 commit comments

Comments
 (0)