Giter Club home page Giter Club logo

windowsstatetriggers's Introduction

UPDATE: Moved to Windows Community Toolkit

Most of these triggers has been moved to the Windows Community Toolkit and is where you'll see future enhancements happen. See:

WindowsStateTriggers

A collection of custom visual state triggers

Sponsoring

If you like this library and use it a lot, consider sponsoring me. Anything helps and encourages me to keep going.

See here for details: https://github.com/sponsors/dotMorten

NuGet

Get it on nuget:

   PM> Install-Package WindowsStateTriggers 

See more information on my blog: http://www.sharpgis.net/post/2015/03/24/Using-Custom-Visual-State-Triggers

Triggers available:
  • DeviceFamilyStateTrigger: Trigger based on the device family (Desktop, Mobile, IoT or Team)
  • NetworkConnectionStateTrigger: Trigger if internet connection is available or not
  • OrientationStateTrigger: Trigger based on portrait/landscape mode
  • IsTrueStateTrigger: Trigger if a value is true - REMOVED ! use StateTrigger and bind to IsActive
  • IsFalseStateTrigger: Trigger if a value is false
  • IsNullOrEmptyStateTrigger: Trigger if an object is null, or if a String or IEnumerable is empty
  • IsTypePresentStateTrigger: Trigger if a type is present (ie hardware backbutton etc)
  • EqualsStateTrigger: Trigger if Value is equal to EqualTo
  • NotEqualStateTrigger: Trigger if Value is not equal to NotEqualTo
  • CompareStateTrigger: Trigger if Value is equal, less than or greater than CompareTo
  • InputTypeTrigger: Trigger based on the PointerType you're using on the TargetElement
  • RegexStateTrigger: This trigger evaluates a regular expression against a string and triggers if a match is found.
  • CompositeStateTrigger: This trigger combines other triggers using, And, Or or Xor to create even more powerful triggers.

Run the test app to see a set of examples of these in use.

windowsstatetriggers

windowsstatetriggers's People

Contributors

cmaneu avatar davesmits avatar dotmorten avatar marcominerva avatar robertos avatar scottisafool avatar tibitoth avatar timheuer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

windowsstatetriggers's Issues

Add all device families to DeviceFamilyAdaptiveTrigger

The DeviceFamilyAdaptiveTrigger supports the Phone, Desktop and universal families but not

  • Team (Surface Hub). Family name: Windows.Team
  • Xbox. Family name: Windows.Xbox
  • IoT (currently returns 'Universal' but that's a bug in current release)
  • HoloLens. Family name: Unknown. Microsoft: Please send @dotMorten a device to test on :)

CompositeStateTrigger does not work with MVVM

When trying to use CompositeStateTrigger with a ViewModel the PropertyChangedCallback of the Dependency Property of the inner StateTrigger is only fired once upon page load and never again. The examples in the TestApp project, which do not use MVVM and bind directly to the page elements, work as intended.

To Reproduce:

To reproduce the issue I have put together a simple example project. Please note that the EqualsStateTrigger should already use the fix mentioned in issue #37.

View - MainPage.xaml
<Page
    x:Class="TestComposite.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestComposite"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wst="using:WindowsStateTriggers"
    mc:Ignorable="d">

    <Page.DataContext>
        <local:MainViewModel />
    </Page.DataContext>

    <Page.Resources>
        <x:Boolean x:Key="TrueValue">True</x:Boolean>
        <x:Boolean x:Key="FalseValue">False</x:Boolean>
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <wst:CompositeStateTrigger Operator="And">
                            <wst:EqualsStateTrigger Value="{Binding IsOption1Checked}" EqualTo="{StaticResource TrueValue}" />
                            <wst:EqualsStateTrigger Value="{Binding IsOption2Checked}" EqualTo="{StaticResource TrueValue}" />
                        </wst:CompositeStateTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="optionStatus.Text" Value="Both options are checked" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <wst:EqualsStateTrigger Value="{Binding IsOption1Checked}" EqualTo="{StaticResource TrueValue}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="optionStatus.Text" Value="Option 1 is checked" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <wst:EqualsStateTrigger Value="{Binding IsOption2Checked}" EqualTo="{StaticResource TrueValue}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="optionStatus.Text" Value="Option 2 is checked" />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <CheckBox Grid.Row="0" Margin="3" Content="Option 1" IsChecked="{Binding IsOption1Checked, Mode=TwoWay}" />
        <CheckBox Grid.Row="1" Margin="3" Content="Option 2" IsChecked="{Binding IsOption2Checked, Mode=TwoWay}" />
        <TextBlock x:Name="optionStatus" Grid.Row="2" Margin="3"/>
    </Grid>
</Page>
ViewModel - MainViewModel.cs
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace TestComposite
{
    public class MainViewModel : INotifyPropertyChanged
    {
        public bool IsOption1Checked
        {
            get { return _isOption1Checked; }
            set
            {
                if (_isOption1Checked == value) return;

                _isOption1Checked = value;
                RaisePropertyChanged();
            }
        }
        private bool _isOption1Checked = false;

        public bool IsOption2Checked
        {
            get { return _isOption2Checked; }
            set
            {
                if (_isOption2Checked == value) return;

                _isOption2Checked = value;
                RaisePropertyChanged();
            }
        }
        private bool _isOption2Checked = false;

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged([CallerMemberName]string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion INotifyPropertyChanged
    }
}

NuGet packages?

When I try to run the project, I get:

Severity Code Description Project File Line
Error This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is ..\packages\Microsoft.Diagnostics.Tracing.EventSource.Redist.1.1.14-beta\build\portable-net45+win8+wpa81\Microsoft.Diagnostics.Tracing.EventSource.Redist.targets. TestApp C:\Users\davev_000\Desktop\WindowsStateTriggers-master\src\TestApp\TestApp.csproj 209

Any suggestions?

CompositeTrigger stops property changed notifcations

If I add two triggers to the CompositeTrigger then the second of the two trigger's dependency properties stops receiving any value changed notifications, if I use either of the two triggers on their own they work fine.

To reproduce:
Add two triggers into the CompositeTrigger that have bindable values. If the property bound to the second trigger changes, notice that the dependency property doesn't get told that the value has changed.

CompareStateTrigger, EqualsStateTrigger and NotEqualStateTrigger can return unexpected results

CompareStateTrigger, EqualsStateTrigger and NotEqualStateTrigger, since it uses EqualsStateTrigger internally, can return unexpected results because they use == for comparison rather than object.Equals(…). The result is a reference comparison when that was probably not intended.

Fixes:

Change comparisons from using == to object.Equals(…).

CompareStateTrigger.cs
internal Comparison CompareValues()
{//if (v1 == v2) OLD METHOD
    if (object.Equals(v1, v2)) // NEW METHOD
    {
        if (Comparison == Comparison.Equal)
            return Comparison.Equal;
    }}
EqualsStateTrigger.cs
internal static bool AreValuesEqual(object value1, object value2, bool convertType)
{
    //if (value1 == value2) OLD METHOD
    if (object.Equals(value1, value2)) // NEW METHOD
    {
        return true;
    }}

To Reproduce:

The provided example shows the issue with the EqualsStateTrigger, using boolean values. CompareStateTrigger seems to do better in this particular case because it uses IComparable when possible. However, CompareStateTrigger has given me similar issues using enums. I can provide an example of the latter as proof if necessary.

MainPage.xaml
<Page
    x:Class="TestComparisons.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestComparisons"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:wst="using:WindowsStateTriggers"
    mc:Ignorable="d">

    <Page.Resources>
        <x:Boolean x:Key="TrueValue">True</x:Boolean>
        <x:Boolean x:Key="AnotherTrueValue">True</x:Boolean>
    </Page.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup>
                <VisualState>
                    <VisualState.StateTriggers>
                        <wst:EqualsStateTrigger Value="{StaticResource TrueValue}" EqualTo="{StaticResource AnotherTrueValue}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="comparisonStatus.Text" Value="The values match, as expected" />
                    </VisualState.Setters>
                </VisualState>
                <VisualState>
                    <VisualState.StateTriggers>
                        <wst:NotEqualStateTrigger Value="{StaticResource TrueValue}" NotEqualTo="{StaticResource AnotherTrueValue}" />
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="comparisonStatus.Text" Value="The values do not match! Unexpected." />
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

        <TextBlock x:Name="comparisonStatus" Margin="3" />
    </Grid>
</Page>

Use weak event listeners

The following triggers are listening to global events and should use weak event listeners:

  • OrientationStateTrigger
  • NetworkConnectionStateTrigger

Without it, they will leak memory

OrientationStateTrigger only works once

Hello,
I've started from scratch with a new solution in VisualStudio 2015 Version 14.0.23107.0 D14REL,
i added your classes with nuget console: Install-Package WindowsStateTriggers

The application starts in portrait mode, then I rotate left or right , the text changes in: landscape .. I rotate again left or right .. the text no longer changes

what am I doing wrong?
plz help

In the MainPage.xaml i added your Code of the TestApp:

<Page
.
.
.
xmlns:triggers="using:WindowsStateTriggers"
mc:Ignorable="d">

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <VisualStateManager.VisualStateGroups>

        <VisualStateGroup >
            <VisualState x:Name="landscape">
                <VisualState.StateTriggers>
                    <triggers:OrientationStateTrigger Orientation="Landscape" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="orientationStatus.Text" Value="Landscape mode" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="portrait">
                <VisualState.StateTriggers>
                    <triggers:OrientationStateTrigger Orientation="Portrait" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="orientationStatus.Text" Value="Portrait mode" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <TextBlock x:Name="orientationStatus" 
            HorizontalAlignment="Center" 
            VerticalAlignment="Center" />
</Grid>

StateTriggers in ListView Datatemplate

Is or will it ever be possible to use custom state triggers in a DataTemplate? All my attempts so far have lead to either nothing happening or a NullReferenceException on the Value binding.

Add Regex state trigger

Add support for a trigger that evaluates a string against a regular expression

regextrigger

<triggers:RegexStateTrigger Value="{x:Bind emailTextBox.Text, Mode=OneWay}"
        Expression="^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$"
        Options="IgnoreCase"
        />

Add ProjectReunion support

Add build for net5.0-windows10.0.19041.0 and <PackageReference Include="Microsoft.ProjectReunion.WinUI" Version="0.5.0-prerelease" />

Hand Preference Trigger

Create a new trigger that actives when the user has a hand preference set to a specific value (left or right handed) in Windows settings.

Triggering events at startup

Hi,

I've incorporated OrientationStateTrigger into an App, it works really well when I change the orientation of the device, but at startup of the app, the trigger does not get called and therefore the visual adaptations are not applied based upon the orientation.

I've tried to determine a method from the source code to execute the trigger when the app is first started, but so far have not found a method.

Can this functionality to execute the trigger on startup of the app be added to the test app for reference, or if it is there already and I've missed it, identify it with a comment?

Thanks.

WeakEventListener usage holds strong reference

Suspect the usage of WeakEventListener is incorrect. E.g.,

var weakEvent = new WeakEventListener<AdaptiveTrigger, CoreWindow,
                                     WindowSizeChangedEventArgs>(this)
{
    OnEventAction = (instance, s, e) => OnCoreWindowOnSizeChanged(s, e),
    ...
};

private void OnCoreWindowOnSizeChanged(CoreWindow sender, WindowSizeChangedEventArgs args)
{

OnEventAction is assigned an lambda. The lambda captures this (implicitly as this.OnCoreWindowOnSizeChanged). Thus weakEvent holds a strong reference to event target this.

Thanks for this inspiring project!

CompositeTrigger logic for XOR operator is nor correct for more than 2 inputs

The XOR operation is defined as true if an odd number of inputs is true, and false otherwise (source: MathWorld). The XOR operation defined on the CompositeStateTrigger does not respect this definition for 3 or more inputs (for example, by the mathematical definition XOR(True,True,True) == True, while the currently defined operation returns False).

We should fix or remove the current XOR operator, and possibly define a new operation which could be called "OnlyOne" that does what the current XOR does.

(Side note: Other potentially useful operations could be "None", "NotAll", specify a maximum/minimum number of satisfied triggers, etc...)

Add Inverse option

There are Triggers like IsEqualTo and IsNotEqual to, but we have others like IsNullOrEmpty but not a reverse. Maybe it would be better to standardise all of these and have a bool property on each that says if you want it normal or reversed?

Right now I want to goven two states, one on when somthing is null, the other when it's not null...

`NullReferenceException` with `{x:Bind}` inside generated code

I'm trying to set a EqualsStateTrigger in a VisualState.StateTriggers with the following code:

<VisualState>
    <VisualState.StateTriggers>
        <triggers:EqualsStateTrigger Value="{x:Bind NavView.IsPaneOpen, Mode=OneWay}" EqualTo="True"/>
    </VisualState.StateTriggers>
    <VisualState.Setters>
        <Setter Target="HorizontalAlignment" Value="Left"/>
    </VisualState.Setters>
</VisualState>

as taken from the example (https://github.com/dotMorten/WindowsStateTriggers/blob/master/src/TestApp/Samples/EqualsSample.xaml)

however it throws NullReferenceException during InitializeComponents().

====== Investigation... ======

digging into generated code (MainPage.g.cs), it calls

public static void Set_WindowsStateTriggers_EqualsStateTrigger_Value(global::WindowsStateTriggers.EqualsStateTrigger obj, global::System.Object value, string targetNullValue)
{
    if (value == null && targetNullValue != null)
    {
        value = (global::System.Object) global::Windows.UI.Xaml.Markup.XamlBindingHelper.ConvertValue(typeof(global::System.Object), targetNullValue);
    }
    obj.Value = value;
}

where obj == null...

I also dug into public void Connect(int connectionId, global::System.Object target) , seems it doesn't call Connect with the IDs for my EqualsStateTriggers:

case 9: // Pages\MainPage.xaml line 138
    this.obj9 = (global::WindowsStateTriggers.EqualsStateTrigger)target;
    break;
case 10: // Pages\MainPage.xaml line 126
    this.obj10 = (global::WindowsStateTriggers.EqualsStateTrigger)target;
    break;

before calling

XamlBindingSetters.Set_WindowsStateTriggers_EqualsStateTrigger_Value(this.obj9, obj, null);

My stack:

MyApp.exe!MyApp.Pages.MainPage.XamlBindingSetters.Set_WindowsStateTriggers_EqualsStateTrigger_Value(WindowsStateTriggers.EqualsStateTrigger obj, object value, string targetNullValue)
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Update_NavView_IsPaneOpen(bool obj, int phase)
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Update_NavView(Microsoft.UI.Xaml.Controls.NavigationView obj, int phase)
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Update_(MyApp.Pages.MainPage obj, int phase)
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Update()
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Initialize()
MyApp.exe!MyApp.Pages.MainPage.MainPage_obj1_Bindings.Loading(Windows.UI.Xaml.FrameworkElement src, object data)

I'm targeting Windows 10, version 1903 (10.0 build 18362) (both target and minimum).

SetTriggerValue

The sample project/triggers seems to have a few errors. The SetTriggerValue function is not available anywhere, and the .SetTriggerValue extension seems to be missing.

Ok. I think I've fixed it. Replace all references to SetTriggerValueReplace with SetActive

Create ConditionStateTriggerBase<T> base type

Many of the existing triggers have quite some boilerplate code, and follow the same structure: they take a Value of some type T, and activate when some condition Predicate<T> is met.

We could make a base class that would greatly reduce the boilerplate that would only expose one public property Value and a protected method or property Condition (a Predicate<T>), and that would reduce keep the trigger implementations limited to the "meaty part". Of course this base class could be inherited by 3rd parties who would like to create their own triggers based on simple conditions.

In the current library, the triggers that would benefit from this base trigger would be:

  • CompareStateTrigger
  • EqualsStateTrigger
  • IsFalseStateTrigger
  • NotEqualStateTrigger
  • IsNullOrEmptyStateTrigger (WIP)

CompositeStateTrigger cannot have AdaptiveTrigger in collection

Unfortunately the following code does not work, but I'd love to have setters for e.g. "desktop device family and window width greater than 500px":

<VisualState.StateTriggers>
    <windowsStateTriggers:CompositeStateTrigger Operator="And">
        <windowsStateTriggers:DeviceFamilyStateTrigger DeviceFamily="Desktop" />
        <AdaptiveTrigger MinWindowWidth="500" />
    </windowsStateTriggers:CompositeStateTrigger>
</VisualState.StateTriggers>

Is there anything that can be done?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.