WPF – Panel Slide-In Animation From Left Or Right Side

Button Click Slides in Panel

Goal

Create a panel which slides in from the right when a button is clicked. The second goal is to have it all done in Xaml with no codebehind code. This article describes how to do that and explains the process behind what is needed in a step by step process. Page #2 below has a link to the full code if one does not need the explanation.

Process

The picture here shows the final code in action where a ToggleButton switches it’s state (IsChecked) between true and false. When that state changes to true it will have the panel slide in from the right and false will have it slide back.

The process described below can be done by placing the code snippets in Xaml and switching to the Design view of Visual Studio.

Un-Moved Rectangle in Design Mode with and without TranslateTransform

The Panel is a Blue Rectangle

For the example we will use a basic Rectangle and place it on the screen in a plain Grid. The panel will be blue an it will reside on the right side of the screen. Here is the initial code, note in future code examples I will omit the Marigin and the alignments for the sake of brevity; but those omitions are needed and will be required in the final code.

<Grid>
    <Rectangle Fill="Blue" Width="100" Height="100" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,0,0"  />
</Grid>

Not Understanding TranslateTransform Is The First Hurdle

When researching and applying the concepts found, I did not understand the importance of TranslateTransform coordinates in this process. When I learned about this concept, other things fell into place.

What TranslateTransform process is, is that each object on the screen has a location, and that location is it’s anchor, so to speak. When one changes the TranslateTransform of an object, it moves it off its anchor and can be shifted right, left, up, or down by changes X and Y values from that initial position.

To achieve movement as mentioned one must provide the initial anchor point to the Rectangle. Below is a non-moved anchoring of the panel at "0,0" so it will appear the on the screen with 0 movement(s).

<Rectangle ...>
   <Rectangle.RenderTransform>
       <TranslateTransform X="0" Y="0" />
   </Rectangle.RenderTransform>
 </Rectangle>

Start it off the screen

Image moved 100 X pixels off its Anchor as shown in Design Mode

What we need now is to, adjust what we have, but start it out of sight to the right *side* of the screen. To achieve this we will change the above translate transform coordinates to instead move the X value and have the start in the off page position. To do that change the existing to this:

<TranslateTransform X="100" Y="0" />

Play with it in design mode by changing the X and Y values and not how it moves around from its initial anchor point.

Set Associative Values

Currently our panel has a Width of 100 and we want to move it off the screen, *and move it back* by that amount; an offset slide amount. What we will do is in the Grid Resource section, *though it could be placed in the page’s Resource section*, is a constant which we will apply to the panel’s Width and the X as an initial offset value.

    <Grid>
        <Grid.Resources>
            <system:Double x:Key="SlideOffSet">100</system:Double>
        </Grid.Resources>

        <Rectangle Width="{StaticResource SlideOffSet}" Height="100" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,10,0,0" >
            <Rectangle.RenderTransform>
                <TranslateTransform X="{StaticResource SlideOffSet}" Y="0" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Grid>

Check the design mode…it should still be off the screen and in the same dimensions as specified in the previous section.

Add a ToggleButton To Change States

We’ve added a toggle button which centers itself and reports its check status

We add a toggle button above the Rectangle panel because we want the panel to be drawn last; so to have it have the highest Zindex. So when it slides in, it will be above all other controls.

<Grid>
    <ToggleButton Height="30" Width="60" Margin="0,20,0,20" x:Name="SlideState">
        <TextBlock Text="{Binding IsChecked, ElementName=SlideState}"
                       FontSize="18" 
                       VerticalAlignment="Center" HorizontalAlignment="Center"  >
        </TextBlock>
    </ToggleButton>

    <Rectangle ...

The Animation Magic To Move It In and Out

To do this we will use Storyboards which when triggered will change the panel’s TranslateTransform X value to and from our slide offset. Go ahead and add the StoryBoards below under the SlideOffset setting in the Resources section.

<Storyboard x:Key="SlideRight">
    <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
                     From="0" To="{StaticResource SlideOffSet}"
                     Duration="0:0:0.3" />
</Storyboard>

<Storyboard x:Key="SlideLeft">
    <DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
                     From="{StaticResource SlideOffSet}" To="0" 
                     Duration="0:0:0.3" />
</Storyboard>

The above code basically changes the target control, in our case the Rectangle, and shifts the X transform anchor value.

Initiate The Dark Move Magic On Button Click

Believe it or not, but we are not finished. The final bit of code has us, again, putting code in the Resource section which will define a style for our Rectangle.

This style is a trigger which is based, bound, off of the value of the IsChecked and depending on its value, initiates the SlideLeft (to move into view) and the SlideRight to move it back off the screen.

<Style TargetType="{x:Type Rectangle}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsChecked, ElementName=SlideState}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource SlideLeft}" />
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource SlideRight}" />
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

Final Thoughts & Code

On the following page (#2) is the full code for your perusal, with no changes from above. For me learning how to position a panel off the screen and then move it was trial and error of internet searches and reading StackOverflow posts. Each component on its own is understandable, but has to be consumed in a certain order. This post is that order in which I would have liked to have read first.

To further your understanding of this see Transforms Overview on Microsoft’s documentation.

Full Code on Page 2 —-(*if link to page #2 is not seen below, load the whole article and scroll down*)——–>

Share

Copy Directory Files and Create Random Names In PowerShell

I had a need to take an existing directory with a specific set of files and create new copies of those files, but with new random names. These new files would test a process which needed a lot of files to be loaded and the files had to be of a specific format and data such as a zip archive.

gci {TargetDirectory} -file  | Copy-Item -Destination { "$([System.IO.Path]::GetRandomFileName()).{Target Extension}" } -whatif

  • This operation copies the file to the current directory.
  • The GetRandomFileName will generate both random text and random lettered extensions.

I needed my files to be all of the same type so I this is the format I used:

gci C:\Test\Initial -file  | Copy-Item -Destination { "$([System.IO.Path]::GetRandomFileName()).zip" } -whatif

Share

Using Cisco AnyConnect In A Virtual Machine

Using Cisco AnyConnect In A Virtual Machine is Problematic. This post details how to enable that operation from within the virtual machine.


ISSUE

When one attempts to run the vpn in a virtual they are presented with:

Cisco Failure

The actual error is:

VPN establishment capability from a remote desktop is disabled. A VPN connection will not be established.VPN establishment capability from a remote desktop is disabled. A VPN connection will not be established.


Cisco Resolution (InComplete)

Cisco advises to resolve by changing the value WindowsVPNEstablishment to AllowRemoteUsers and references a now defunct web page.

How to enable Cisco Anyconnect VPN through Remote Desktop

Unfortunately it does not specify if that is on the server or client.

Resolution (Client)

To resolve the issue one has to intercept a downloaded file CHS-TwoFactor-VPN_client-profile.xml downloaded/modified during connection and change 1 or more settings in this file. This method was proposed by the post Bypassing Cisco AnyConnects profile settings by Joao. His method was to create a C# filewatcher which when the XML file changed, to replace it with a settings file that had WindowsVPNEstablishment as well as WindowsLogonEnforcement commented out. But I found that his code/methodology had a couple of problematic issues which could cause it to fail. Specifically the value of the key WindowsVPNEstablishment needs to be set to AllowRemoteUsers and not just commented out I document my solution below.

Xml Changes

Before

<WindowsLogonEnforcement>SingleLocalLogon</WindowsLogonEnforcement>
<WindowsVPNEstablishment>LocalUsersOnly</WindowsVPNEstablishment>

After

<WindowsLogonEnforcement>SingleLocalLogon</WindowsLogonEnforcement>
<WindowsVPNEstablishment>AllowRemoteUsers</WindowsVPNEstablishment>

Note that I do not change the WindowsLogonEnforcement as advised by Joao because I am surmising that I only have one connection to coporate at a time which is in the Virtual Machine. I believe that this setting is for multiple connections(?) … so if you run into further issues, that may need to be addressed.

C# Code

Design Considerations

  • C# program which can be compiled outside of Visual Studio by C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe {filename}.cs
  • Deletes the existing initial XML file as first step. Requiring a new download by the CISCO process.
  • Watch the directory %ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile for changes.
  • When change of Created is thrown, delete downloaded file and replace with backup file in the same directory which has aformentioned xml changes ready to go.
class Program
{
    static string FileName => "CHS-TwoFactor-VPN_client-profile";
    static string Directory => @"C:\ProgramData\Cisco\Cisco AnyConnect Secure Mobility Client\Profile";
    static string PathedFileName => $@"{Directory}\{FileName}.xml";

    static bool HasReplaced = false;
    static void Main(string[] args)
    {
        Console.WriteLine($"Watcher started on Directory{Environment.NewLine}{Directory}");

        DeleteFile();

        var watcher = new FileSystemWatcher(Directory);
        watcher.EnableRaisingEvents = true;

        watcher.Created += Watcher_Changed;
        watcher.Changed += Watcher_Changed;
        watcher.Deleted += Watcher_Changed;

        while (!HasReplaced)
            System.Threading.Thread.Sleep(50);

        watcher.Created -= Watcher_Changed;
        watcher.Changed -= Watcher_Changed;
        watcher.Deleted -= Watcher_Changed;

        watcher = null;
    }

    private static void Watcher_Changed(object sender, FileSystemEventArgs e)
    {
        if ((e.ChangeType == WatcherChangeTypes.Created) || (e.ChangeType == WatcherChangeTypes.Changed))
        {
            switch (e.ChangeType)
            {
                case WatcherChangeTypes.Created: Console.WriteLine("Created Event"); break;
                case WatcherChangeTypes.Changed: Console.WriteLine("Changed Event"); break;
            }
            ReplaceFile();
        }
    }

    static void ReplaceFile()
    {
        DeleteFile();

        File.Copy($@"{Directory}\{FileName}.bak", $@"{Directory}\{FileName}.xml"); 

        HasReplaced = true;
        Console.WriteLine("File Replaced");
    }

    static void DeleteFile()
    {
        if (File.Exists(PathedFileName))
        {
            File.Delete(PathedFileName);
            Console.WriteLine($"Removing {FileName}.xml");
        }
    }
}

Usage

XML File

  1. In the %ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile create a backup file named CHS-TwoFactor-VPN_client-profile.bak with the changes mentione in the XML Changes section.

This is used by the C# program to replace the downloaded file from Cisco at the right moment.

C# File

  1. Copy the exe (only ignore other uneeded files) generated into a directory on the virtual machine.
  2. Create a shortcut on the desktop to the file. (in Explorer Drag exe file while holding CTRL-Shift to create a link).
  3. Right Click the Link on the desktop and Run as administrator.
  4. Login through AnyConnect.

Note that the program will show status and if you want to see that status, run the program from a command shell which is run as an administrator.

Share

Verify All Multiple Downloaded Files’ Checksum In Powershell

I ran into this need while downloading the Oracle VirtualBox Image for its Developer Database which was 7ziped into 14 files. I wanted a way to view all the checksums using Windows 10 certutil program without having to type it into the command line. Here is the command used from the directory.:

     #
     gci  | foreach { certutil -hashfile $_.fullname MD5 }
     

I had other files in the directory so I wanted to filter only on those files:

     #
     gci -filter *.ova.7z.0** | foreach { certutil -hashfile $_.fullname MD5 }

Share

Identify Invalid Azure Container Names Using .Net Regex

Not finding a satisfactory method to find invalid Azure Container names, I wrote my own easier (?) to read regex pattern for .Net.

^                       # Anchor; beginning of line. 
(?!.+--)                # String ahead does not contain two dashes 
(?!^-)                  # String ahead does not start with a dash 
(\$root|[a-z\d-]{3,63}) # Either literal root or a combination of lower case. 
$                       # Anchor; end of line

 

Using a negative look ahead convention (which does not match anything) to handle the double dash situation makes it easier to read.

The first rule says from the beginning of the line, there should not be two dashes or to start with a dash. Once valid, then either match the literal text “$root” or then match only lower case letters, numbers or a dash for a total of three characters to 63 characters.

Remember to run the above pattern with IgnorePatternWhiteSpace, which allows us to comment it. Or run without any option by specifying it on one line:

^(?!.+--)(?!^-)(\$root|[a-z\d-]{3,63})$

Here are the rules for Container names:

Valid naming for a Container in Azure Blob Storage.

1.  3 to 63 Characters

2.  Starts With Letter or Number

3.  Letters, Numbers, and Dash (-)

4.  Every Dash (-) Must Be Immediately Preceded and Followed by a Letter or Number

5.  All letters in a container name must be lowercase.

Share

Entity Framework Stored Procedure Instructions

This is a how-to on getting Entity Framework (EF) version 5 and 6 to include stored procs and how to consume the resulting entities in code.

  1. In the EF designer choose `Update Model From Database`.
  2. When the page to `Choose Your Database Objects and Settings` comes up which allows one to add new tables/views/stored procs, select the stored proc of interest. Remember the name for the resulting data mapping entity will be the name with the extension `_Result`.2015-06-12_19-10-39
  3. Once the wizard is finished EF will contain the stored proc in the `Model Browser`. The model browser can be displayed by right clicking the EF design surface and selecting `Model Browser`.2015-06-12_19-51-20
  4. Here is an explanation of what has happened.
    (1) You have added the stored proc into the `Stored Procedures __abENT__#8260; Functions` as an item of interest.
    (2) EF has created a function import of the stored proc and placed it into `Function Imports`.
    (3) If EF was able to determine the *result set entity* it will most likely be in the `Complex Types` folder.
  5. If the mapping has gone right you should be able to call the stored proc off of the EF context in code and it will return a list of the complex type `xxx_Result`. If it works you will know it, but there could be problems with the mapping.

Mapping Problems and How to Resolve

  • One can delete at anytime the any object in the folders of 1/2 or 3 shown above and regenerate or create a custom mapping. Don’t be afraid to delete.
  • Sometimes very complex stored procs will not divulge the right mapping of the entity in the result set and the resulting complex type will cause failures. One way around that is to create a faux data return in the stored proc which leaves no ambiguity for Ef.
          1. In the database change the stored proc as follows.  Comment out the meat of the result select and replace it with a one-to-one column stub faux select such as this example: “SELECT 1 AS ResultId, ‘Power1’ AS GroupName, ‘Test’ AS Description”. Note to be clear you will need to match every column and name.
          2. In EF’s Model Browser delete all things associated with the stored proc in folders 1, 2 and 3 above.
          3. Regenerate all by using`Update Model From Database`.
          4. Check the results.
  • If the above steps fail one can always create a function mapping by hand. Be careful not to create duplicates, if so delete all and start over.
        • Open up and find the stored proc you inserted into folder #3 above. Right click and select`Add Function Import…`2015-06-12_20-09-09
        • One can get the column information, change items on the above screen; it is trial and error.
        • You will need to play around with this until you have the right columns for your function import. Be wary of numbered copiesof the complex types which may be created from the mapping.

Remember to reset the stored proc back to its original state instead of the faux stub mentioned.

Share

Entity Framework Cascading Deletes; Set it from the database.

To achieve cascading deletes, one must specify the cascading deletes on the FK relationships from the top level table in the database. The default is not to cascade.

Here is the visual Process in SQL Server Management Studio.

  1. Select the top level table which will handle the delete and right click.
  2. Select design mode.
  3. Right click any row in the design mode.
  4. Select Relationships.
  5. Find all the FK relationships and set them to cascade.

Then in Entity Framework update the edmx file after these changes are made so entity framework knows about the cascading constraint.  Once all this is done a cascaded delete is possible using Entity Framework.

 

omegacoder_dot_com_EF

Share

Visual Studio: How to Resolve TestWindowPackage.Initialize Failure

I began to receive the error message box in Visual Studio after a restart from an install of an unrelated to test Visual Studio plugin (which I have used in the past):

The ‘TestWindowPackage’ package did not load correctly.  … examining the file … AppData\Roaming\Microsoft\VisualStudio\12.0\ActivityLog.xml

Looking at that log showed these errors:

TestWindowPackage.Initialize failed with exception … System.InvalidOperationException:

Loading MEF components failed with the following exception:
The composition produced a single composition error. The root cause is provided below. Review the CompositionException.Errors property for more detailed information.

No exports were found that match the constraint:
    ContractName    Microsoft.VisualStudio.TestWindow.VsHost.PackageContainer
    RequiredTypeIdentity    Microsoft.VisualStudio.TestWindow.VsHost.PackageContainer

 

To resolve the issue I did step 1 and 2 but am showing step 3 in case it helps.

  1. Close all instances of Visual Studio.
  2. Delete all files in `AppData__abENT__#92;Local__abENT__#92;Microsoft__abENT__#92;VisualStudio__abENT__#92;12__abENT__#46;0__abENT__#92;ComponentModelCache` Note that directory is not found in `Roaming` as the activity log file, but in `Local`.
  3. Restart, if that doesn’t work then start over with step 4.
  4. From a Visual Studio Command Line do this operation: `devenv __abENT__#8260;setup __abENT__#8260;ResetSkipPkgs` See (/Setup (devenv.exe)) for more information.
Share