Showing posts with label wpf. Show all posts
Showing posts with label wpf. Show all posts

Sunday, August 5, 2018

How do I assign a global initialized event?

Leave a Comment

I've got this code in my App.xaml.cs:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(TextBox), TextBox.TextChangedEvent, new RoutedEventHandler(TextBox_TextChangedEvent)); } private void TextBox_TextChangedEvent(object sender, RoutedEventArgs e) {     // Works } 

I would like to do something similar for the InitializedEvent.
Here's my failed attempt:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.InitializedEvent, new EventHandler(FrameworkElement_InitializedEvent)); } private void FrameworkElement_InitializedEvent(object sender, EventArgs e) {  } 

Is the InitializedEvent somewhere else?
Is this even possible?

I've tried using the LoadedEvent:

protected override void OnStartup(StartupEventArgs e) {     EventManager.RegisterClassHandler(typeof(FrameworkElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(FrameworkElement_LoadedEvent)); } private void FrameworkElement_LoadedEvent(object sender, RoutedEventArgs e) {     // Fires only for Windows } 

It only fired for Windows and not the controls inside the Windows. I did realize though; that when I added a loaded event to a Label that I had inside my Window; the global FrameworkElement_LoadedEvent fired for that Label even though my normal loaded event (That I made for the Label specifically) was empty. I've also tried these:

EventManager.RegisterClassHandler(typeof(Button), Button.LoadedEvent, new RoutedEventHandler(Button_LoadedEvent)); EventManager.RegisterClassHandler(typeof(Grid), Grid.LoadedEvent, new RoutedEventHandler(Grid_LoadedEvent)); EventManager.RegisterClassHandler(typeof(DataGrid), DataGrid.LoadedEvent, new RoutedEventHandler(DataGrid_LoadedEvent)); 

But they don't fire unless I add another empty loaded event on those controls specifically.

My goal is to build up a sort of a time log of every control that becomes initialized.

How can I achieve this without adding loaded events on every single control I have?

(I have a lot)

1 Answers

Answers 1

Here you are!

public partial class App : Application {     // ##############################################################################################################################     // Constructor     // ##############################################################################################################################      #region Constructor      static App()     {         // set MyInitialized=true for new windows (happens before Loaded)         EventManager.RegisterClassHandler(typeof(Window), FrameworkElement.SizeChangedEvent, new RoutedEventHandler(OnSizeChanged));          // our loaded handler         EventManager.RegisterClassHandler(typeof(UIElement), FrameworkElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);         EventManager.RegisterClassHandler(typeof(ContentElement), FrameworkContentElement.LoadedEvent, new RoutedEventHandler(OnLoaded), true);     }      private static void OnSizeChanged(object sender, RoutedEventArgs e)     {         //Console.WriteLine("SizeChanged {0}", sender);         SetMyInitialized((Window) sender, true);     }      private static void OnLoaded(object sender, RoutedEventArgs e)     {         Trace.WriteLine($"{DateTime.Now:O}: {sender} loaded");     }      #endregion      // ##############################################################################################################################     // MyInitialized     // ##############################################################################################################################      #region MyInitialized      public static void SetMyInitialized(UIElement element, bool value)     {         element.SetValue(MyInitializedProperty, value);     }      public static bool GetMyInitialized(UIElement element)     {         return (bool) element.GetValue(MyInitializedProperty);     }      public static readonly DependencyProperty MyInitializedProperty = DependencyProperty.RegisterAttached("MyInitialized", typeof (bool), typeof (App), new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.Inherits, OnMyInitializedChanged));      private static void OnMyInitializedChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs ev)     {         if ((bool)ev.NewValue)         {             // registering instance handler unbreaks class handlers             if (dpo is FrameworkElement element)                 element.Loaded += _EmptyRoutedEventHandler;             if (dpo is FrameworkContentElement contentElement)                 contentElement.Loaded += _EmptyRoutedEventHandler;         } else         {             throw new ArgumentException("Cannot set to false", ev.Property.Name);         }         //Console.WriteLine("MyInitialized {0} {1}=>{2}", dpo, ev.OldValue, ev.NewValue);     }      private static readonly RoutedEventHandler _EmptyRoutedEventHandler = delegate { };      #endregion               } 

XAML

<Window x:Class="WpfApp3.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:WpfApp3"         mc:Ignorable="d"         Title="MainWindow" Height="450" Width="800"         d:DataContext="{d:DesignInstance local:MainWindow}">         <Grid>             <Border Background="Green" VerticalAlignment="Center" HorizontalAlignment="Center" Width="30" Height="20">                 <TextBlock Background="Orange" Text="hello"></TextBlock>             </Border>         </Grid> </Window> 

Sample Console output:

2018-07-31T14:20:52.6052225+02:00: WpfApp3.MainWindow loaded 2018-07-31T14:20:52.6112064+02:00: System.Windows.Controls.Border loaded 2018-07-31T14:20:52.6132008+02:00: System.Windows.Documents.AdornerDecorator loaded 2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.ContentPresenter loaded 2018-07-31T14:20:52.6141984+02:00: System.Windows.Controls.Grid loaded 2018-07-31T14:20:52.6151966+02:00: System.Windows.Controls.Border loaded 2018-07-31T14:20:52.6161935+02:00: System.Windows.Controls.TextBlock loaded 2018-07-31T14:20:52.6161935+02:00: System.Windows.Documents.AdornerLayer loaded 
Read More

Thursday, July 26, 2018

Set ControlTemplate TemplateBinding in Code

Leave a Comment

I want to set the Foreground in the code behing file. But setting Foreground doesn't change the visual style. FontSize btw works?

<ControlTemplate  x:Key="SimpleBtn" TargetType="Button">       <Button x:Name="btnct" CommandParameter="{Binding Content}" Command="{Binding Path=DataContext.ButtonClickCommand,ElementName=MainGrid}"          keyImageProperty:KeyPressed.Image="{DynamicResource ResourceKey=gbutton70x70}" keyImageProperty:KeyNotPressed.Image="{DynamicResource ResourceKey=button70x70}"           Template="{DynamicResource ResourceKey=KeyboardButton}" Content="{TemplateBinding Content}"           FontSize="{TemplateBinding FontSize}" FontWeight="Medium" Foreground="{TemplateBinding Foreground}" FontFamily="{TemplateBinding FontFamily}"  />  </ControlTemplate>   <DataTemplate x:Name="btndatatemplate" x:Key="itemContDataTemplate" >       <Button x:Name="btnstandard" Template="{DynamicResource ResourceKey=SimpleBtn}"                                                    FontWeight="Bold"                   Content="{Binding Content}"     />   </DataTemplate> 

1 Answers

Answers 1

This should work for setting up templatebinding on the button in code behind (as part of a complete ControlTemplate definition):

var button = new FrameworkElementFactory(typeof(Button)) { Name = "btnct" }; button.SetValue(Button.ForegroundProperty, new TemplateBindingExtension(Button.ForegroundProperty)); 

FontSize works not because the templatebinding is working, but because FontSize is automatically inherited by child controls, whereas foreground is not. (Try the following in XAML:)

<Button FontSize="20" Foreground="Red">      <Button Content="Click"/> </Button> 
Read More

Monday, July 9, 2018

Resizing of ToolWindow and contents in WPF

Leave a Comment

We have a VS extension. The user uses a ToolWindowPane to interact with the extension. The height and width of the ToolWindowPane depends on how the user has their VS environment set up, and currently the contents of the ToolWindowPane does not resize properly.

So here is the window:

public class SymCalculationUtilitiesWindow : ToolWindowPane {     /// <summary>     /// Initializes a new instance of the <see cref="SymCalculationUtilitiesWindow"/> class.     /// </summary>     public SymCalculationUtilitiesWindow() : base(null)     {         this.Caption = "Sym Calculation Utilities";          this.ToolBar = new CommandID(new Guid(Guids.guidConnectCommandPackageCmdSet), Guids.SymToolbar);         // This is the user control hosted by the tool window; Note that, even if this class implements IDisposable,         // we are not calling Dispose on this object. This is because ToolWindowPane calls Dispose on         // the object returned by the Content property.         this.Content = new UtilitiesView();      }  } 

So the UtilitiesView is the default view. Here is the xaml:

<UserControl          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"          xmlns:d="http://schemas.microsoft.com/expression/blend/2008"          xmlns:local="clr-namespace:Sym.VisualStudioExtension" x:Class="Sym.VisualStudioExtension.Engines.UtilitiesView"          xmlns:engines="clr-namespace:Sym.VisualStudioExtension.Engines"           Background="{DynamicResource VsBrush.Window}"          Foreground="{DynamicResource VsBrush.WindowText}"          mc:Ignorable="d"          local:ViewModelLocator.AutoWireViewModel="True"          x:Name="MyToolWindow" Height="800" Width="400">  <UserControl.Resources>     <DataTemplate DataType="{x:Type engines:CalcEngineViewModel}">         <engines:CalcEngineView/>     </DataTemplate>     <DataTemplate DataType="{x:Type engines:TAEngineViewModel}">         <engines:TAEngineView/>     </DataTemplate> </UserControl.Resources>  <Grid>     <Grid.RowDefinitions>         <RowDefinition Height="auto" />         <RowDefinition Height="207*" />         <RowDefinition Height="593*"/>     </Grid.RowDefinitions>     <Grid x:Name="MainContent"         Grid.Row="1" Grid.RowSpan="2">         <Grid.RowDefinitions>             <RowDefinition Height="auto"/>             <RowDefinition Height="auto"/>         </Grid.RowDefinitions>         <ContentControl Content="{Binding CurrentEngineViewModel}" Grid.RowSpan="2"/>     </Grid>  </Grid> 

and the user makes a choice which determines the CurrentEngineViewModel.

The following is the xaml of one of the possible CurrentEngineViewModels:

<UserControl x:Class="Sym.VisualStudioExtension.Engines.CalcEngineView"          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"           xmlns:d="http://schemas.microsoft.com/expression/blend/2008"             xmlns:domain="clr-namespace:Sym.Engines.Calculation.Builder.Domain;assembly=Sym.Engines.Calculation"           xmlns:core="clr-namespace:Sym.Core.Domain;assembly=Sym.Core"           xmlns:helper="clr-namespace:Sym.VisualStudioExtension.Helper_Classes"          xmlns:local="clr-namespace:Sym.VisualStudioExtension"                     local:ViewModelLocator.AutoWireViewModel="True"          mc:Ignorable="d"                       d:DesignHeight="800" d:DesignWidth="400"> <UserControl.Resources>     <ContextMenu>         ...     </ContextMenu> </UserControl.Resources> <Grid Margin="-20,-20,-20,-20">     <Grid.RowDefinitions>         <RowDefinition Height="8*"/>      </Grid.RowDefinitions>     <TabControl x:Name="tabControl" HorizontalAlignment="Left" Height="617" Margin="20,54,0,0" VerticalAlignment="Top" Width="357">         <TabItem Header="Calculation Files">             <ListBox Name="CalcFilesListBox"                       Margin="20" ItemsSource="{Binding CalcFilesList}"                                                 ContextMenu="{StaticResource NewEditDeleteContextMenu}"                      Tag="{x:Type core:CalcFile}">                 ...             </ListBox>                         </TabItem>         <TabItem Header="Template Files" Height="22" VerticalAlignment="Top">             <TreeView ItemsSource="{Binding TemplateFamilyList}"                        Margin="20"                       ContextMenu="{StaticResource NewEditDeleteContextMenu}"                       Tag="{x:Type domain:TemplateParameter}">                 <TreeView.Resources>                     ...                 </TreeView.Resources>             </TreeView>         </TabItem>         <TabItem Header="Advanced Calc Files">             <ListBox Margin="20"                       ItemsSource="{Binding AdvancedCalcFilesList}"                      ContextMenu="{StaticResource NewEditDeleteContextMenu}"                      Tag="{x:Type domain:TemplateCalculation}">                 ...             </ListBox>         </TabItem>     </TabControl>     <Label x:Name="label" Content="{Binding Path=Title}" HorizontalAlignment="Left" Height="27" Margin="10,22,0,0" VerticalAlignment="Top" Width="367"/> </Grid> 

It seems to me that on the ToolWindowPane, there is a Grid, and on the Grid another Grid, and on that Grid, a Tabcontrol. From this post it seems that some controls do not resize. So would that mean that the TabControl can't resize even if it is on a Grid?

When the user resizes the ToolWindowPane, the contents does not resize. How can I achieve correct resizing in this situation?

enter image description here

2 Answers

Answers 1

To make the page salable across resolutions/devices, you must ensure that there are no fixed width/height property specified; instead we can use them in percentage (%) which will make the controls scale based on available viewport. Try replacing all the fixed height & width properties for your control with percentages.

if for some reasons the controls are getting squeezed you can try providing minHeight & minWidth to the control as documented here https://www.w3schools.com/cssref/pr_dim_min-height.asp

Answers 2

The base of the problem is the explicit Width and Height values are being set and preventing the controls from fitting into their container.

Read More

Wednesday, June 27, 2018

QuickInfoSession is dismissed prematurely when using UserControls in quickInfoContent

Leave a Comment

First some boilerplate code; question below.

I have a standard QuickInfoSourceProvider:

[Export(typeof(IIntellisenseControllerProvider))] internal sealed class QuickInfoControllerProvider : IIntellisenseControllerProvider {     [Import]     private IQuickInfoBroker _quickInfoBroker = null;      public IIntellisenseController TryCreateIntellisenseController(ITextView textView, IList<ITextBuffer> subjectBuffers)     {         return new QuickInfoController(textView, subjectBuffers, this._quickInfoBroker);     } } 

And a standard QuickInfoController:

internal sealed class QuickInfoController : IIntellisenseController {     private readonly IList<ITextBuffer> _subjectBuffers;     private readonly IQuickInfoBroker _quickInfoBroker;     private ITextView _textView;      internal QuickInfoController(         ITextView textView,         IList<ITextBuffer> subjectBuffers,         IQuickInfoBroker quickInfoBroker)     {         this._textView = textView;         this._subjectBuffers = subjectBuffers;         this._quickInfoBroker = quickInfoBroker;         this._textView.MouseHover += (o, e) => {             SnapshotPoint? point = GetMousePosition(new SnapshotPoint(this._textView.TextSnapshot, e.Position));             if (point.HasValue)             {                 ITrackingPoint triggerPoint = point.Value.Snapshot.CreateTrackingPoint(point.Value.Position, PointTrackingMode.Positive);                 if (!this._quickInfoBroker.IsQuickInfoActive(this._textView))                 {                     this._quickInfoBroker.TriggerQuickInfo(this._textView, triggerPoint, false);                 }             }         };     }     private SnapshotPoint? GetMousePosition(SnapshotPoint topPosition)     {         return this._textView.BufferGraph.MapDownToFirstMatch(             topPosition,             PointTrackingMode.Positive,             snapshot => this._subjectBuffers.Contains(snapshot.TextBuffer),             PositionAffinity.Predecessor         );     } } 

The QuickInfoSourceProvider is also standaard:

[Export(typeof(IQuickInfoSourceProvider))] internal sealed class QuickInfoSourceProvider : IQuickInfoSourceProvider {     public IQuickInfoSource TryCreateQuickInfoSource(ITextBuffer buffer)     {         Func<QuickInfoSource> sc = delegate () {             return new QuickInfoSource(buffer);         };         return buffer.Properties.GetOrCreateSingletonProperty(sc);     } } 

Now things become interesting: instead of adding a plain string into quickInfoContent I pass in a UserControl (BugWindow); but still, pretty standard:

internal sealed class QuickInfoSource : IQuickInfoSource {     private readonly ITextBuffer _sourceBuffer;     public QuickInfoSource(ITextBuffer buffer)     {         this._sourceBuffer = buffer;     }     public void AugmentQuickInfoSession(IQuickInfoSession session, IList<object> quickInfoContent, out ITrackingSpan applicableToSpan)     {         var snapshot = this._sourceBuffer.CurrentSnapshot;         var triggerPoint = (SnapshotPoint)session.GetTriggerPoint(snapshot);         applicableToSpan = snapshot.CreateTrackingSpan(new SnapshotSpan(triggerPoint, triggerPoint), SpanTrackingMode.EdgeInclusive);         quickInfoContent.Add(new BugWindow());     } } 

The BugWindow.xaml contains an expander, and it is with this expander that the trouble starts. First the code:

<UserControl x:Class="BugWindow"              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"              x:Name="MainWindow">     <Expander GotMouseCapture="GotMouseCapture_Click" IsExpanded="False">Blah</Expander> </UserControl> 

The BugWindow.xaml.cs contains some code to help me understand the problem. My first thoughts were to prevent the mouse event from bubbling to VS, but these experiments did not help...

public partial class BugWindow : UserControl {     public BugWindow()     {         InitializeComponent();          this.MainWindow.MouseLeftButtonDown += (o, i) =>          {             //i.Handled = true; // dont let the mouse event from inside this window bubble up to VS         };           this.MainWindow.PreviewMouseLeftButtonDown += (o, i) =>         {             //i.Handled = true; // if true then no event is able to bubble to the gui         };     }      private void GotMouseCapture_Click(object sender, RoutedEventArgs e)     {         //e.Handled = true;     } } 

What works: if you hover the mouse over a keyword, my BugWindow appears and the expander is closed (because it is closed by default). If you click the expander, it opens and the text "Blah" appears.

Bug: if you leave open the expander and scroll down, the tooltip will disappear when the span the tooltip is applicable to (applicableSpan) is outside the visible window. We are now in the "bug state". If you hover the mouse over any keyword, my BugWindow will appear. If you click the expander, the window will incorrectly disappear. In fact, the quickInfoSession will be dismissed, as if you were clicking where no keywords are, which is interpreted as dismissing the session. Buttons have the same bug behaviour.

Question: How can I debug this: my mouse event gets lost or hijacked. And I like to find out why that happens. But to be honest, I just like my expander to behave as expected.

Edit: A minimal github repo with this bug can be found at https://github.com/HJLebbink/vsix-bug-quickinfosession. Please use the github issues for help.

0 Answers

Read More

Tuesday, June 12, 2018

Windows 10 Pro -version 1803 bluetooth Profiles Access

Leave a Comment

We are looking to access and use Bluetooth profiles in our WPF application using C# in Visual Studio 2017.

Issue details:

Platform: Windows 10 Pro - version 1803.

Issue brief: We are trying to access Bluetooth profiles via desktop(c#) of connected phones, however on windows 10 the profile show enable but the profiles are not working eg: HFP connects, however, the voice is not heard

We have tested this on following Bluetooth devices:

1.Bluetooth CSR 4.0 Dongle (CSR8510 A10) (Note: this Bluetooth connects and show HFP and works as expected, however, the Bluetooth does not show on the device list and hence we cannot connect programmatically using c#)

2.IOGEAR's Bluetooth 4.0 (Model GBU521W6) (Shows on device list and our application can detect a device, however, HFP is not working as expected both from the application or from normal device section)

Required Profiles:

1.Hands-Free Profile (HFP) 2.Message Access Profile (MAP) 3.Phone Book Access Profile (PBAP)

We have Already Tried with following:

  1. Updating drivers
  2. Tried uninstall install many times
  3. Used android, ios, and windows phone's

Side note: Our application with same code works on windows 7

1 Answers

Answers 1

MAP abd PBAP is not a problem because both are OBEX based (which is RFCOMM).

However there can be some problems with HandsFree. It works great with BlueSoile drivers. But with standard microsoft may not work.

The first step it to use BluetoothSetServiceState with HFP UUID to tell windows to install drivers for your device's HFP profile. If function succeed you should see 2 audio devices appeared in your system: one is Inout and other is Output. You can find them using any media API (DirectSound, legacy API).

To be able to work with PBAP and MAP you need anyhow connect to your device through RFCOMM. WinSock or any other way is good.

Please note that the method above works only with Microsoft Bluetooth drivers. Other drivers (BlueSoleil, Toshiba) have absolutely different API so you have to add it into your application if need to support them.

Or you can simple take a look on BluetoothFramework

Read More

Friday, May 25, 2018

A ListView column with an image in its data template is not visible

Leave a Comment

I have the following three data templates:

<HierarchicalDataTemplate DataType="{x:Type models:DirOrFileItem}" ItemsSource="{Binding Children}">     <StackPanel Orientation="Horizontal">         <Image Source="../Images/Folder.png"  Stretch="Uniform" Height="20"></Image>         <TextBlock Text="{Binding Name}" ToolTip="{Binding RelativePath}"></TextBlock>     </StackPanel> </HierarchicalDataTemplate>  <DataTemplate x:Key="SelectColTemplate">     <CheckBox IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}" /> </DataTemplate> <DataTemplate x:Key="IconTemplate">     <Image Source="{Binding ImageData}" Stretch="Uniform" Height="20" /> </DataTemplate> 

I set the ImageData property on the row viewmodel as follows:

item.ImageData = ImageHelper.LoadImage(AppConstants.FileRsourcePath); 

where LoadImage is:

public static BitmapImage LoadImage(string filename) {     return new BitmapImage(new Uri("pack://application:,,,/" + filename)); } 

I know it loads the image correctly because when I examine the ImageData property after setting it, it has properties that are correct for the image that was loaded.

The HierarchicalDataTemplate is for a TreeView, and the image folder.png appears as and where expected. Then I have the following ListView columns:

<GridViewColumn CellTemplate="{StaticResource SelectColTemplate}" Width="30" /> <GridViewColumn CellTemplate="{StaticResource IconTemplate}" Width="30" /> <GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" Width="360" /> 

I am displaying a list of files and folders, and would like an image to highlight which is which.

The CheckBox appears where it should, in the first column, and the third column in the markup appears as the second column on screen, as if the column with the image template, IconTemplate, does not exist.

Both images are where they should be, in the same Images folder, so why is my "image column" not appearing as the second column as I expect?

BONUS QUESTION: If, as @Clemens suggests below in his comment, I set the Build Action of the images to Resource and and load them by Resource File Pack URIs, how would I do so in XAML?

2 Answers

Answers 1

Just set Build Action in your image properties to Resource and set full path to your image. It will appear. http://prntscr.com/jjw4z3

Answers 2

As long you don't need to destroy it....you don't have to load the image, just give the URI in the binding ==> ImageData = new Uri("pack://application:,,,/" + filename)); and the Image control will load it

btw, your viewmodel must not have GUI related element like bitmap image bye.

Read More

Saturday, April 14, 2018

Polygon automatcally adjust to its above polygon

Leave a Comment

I'm making a Windows Desktop Application that have drag and drop functionality. I'm using Polygon (And Images later) Shapes for drag and drop. The drag and drop functionality works fine but I want that if user drag any shape from the panel and when he drag other shape then the second shape automatically fix with first shape. You'll understand it by take a look at below screenshots.

It is the Screen Shot of what happens when I drag Shapes

When user drop the polygon near the other polygon it will automatically adjust itself, if the same polygon drop in other area of canvas than a error will show to the user.

enter image description here

Here is my XAML Code

<Window x:Class="Images.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"         xmlns:local="clr-namespace:Images"         mc:Ignorable="d"         Title="MainWindow" Height="450" Width="800">     <DockPanel          VerticalAlignment="Stretch"          Height="Auto">          <DockPanel              HorizontalAlignment="Stretch"              VerticalAlignment="Stretch"              Height="Auto"              MinWidth="400"             Margin="10">              <GroupBox                  DockPanel.Dock="Left"                  Width="350"                  Background="Aqua"                 VerticalAlignment="Stretch"                  VerticalContentAlignment="Stretch"                  Height="Auto">                 <WrapPanel Margin="0,10,0,0" VerticalAlignment="Top">                     <Button Name="control" Content="Control" Height="30" Background="BlueViolet" Margin="5" Width="100"/>                     <Button Name="motion" Content="Motion" Width="100" Margin="5" Background="Green" Height="30"/>                     <Button Name="variable" Content="Variable" Width="100" Margin="5" Background="SeaGreen" Height="30"/>                     <Button Name="sensor" Content="Sensor" Width="100" Margin="5" Background="OrangeRed" Height="30"/>                     <Button Name="lcd" Content="LCD" Width="100" Margin="5" Height="30" Background="PaleVioletRed"/>                     <Button Name="function" Content="Function" Width="100" Margin="5" Height="30" Background="Salmon"/>                      <StackPanel Name="heaading" Width="350">                         <TextBlock Name="controlName" TextAlignment="Center" Text="Controls"/>                     </StackPanel>                     <StackPanel Name="userControls" Orientation="Vertical">                         <!--  Users Controls Items Goes Here -->                         <Polygon Name="startProgram" Points="80,10, 80, 80, 135,80, 135, 45, 205, 45, 205, 80, 260, 80, 260,10" Fill="Chocolate" Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />                         <Polygon Name="endProgram" Fill="BlueViolet"  Points="80,40, 80,80, 260,80, 260,40, 200,40, 200,10, 140,10,140,40"  Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />                     </StackPanel>                 </WrapPanel>              </GroupBox>              <!-- Change this to Canvas for work later -->             <Canvas x:Name="dropArea" DockPanel.Dock="Right" Margin="10" Background="#FF9760BF" Width="Auto" HorizontalAlignment="Stretch" AllowDrop="True" Drop="dropArea_Drop">              </Canvas>         </DockPanel>     </DockPanel> </Window> 

Here is my CS code

namespace Images {     /// <summary>     /// Interaction logic for MainWindow.xaml     /// </summary>     public partial class MainWindow : Window     {         public MainWindow()         {             InitializeComponent();         }          private void dropArea_Drop(object sender, DragEventArgs e)         {             var shape = e.Data.GetData(typeof(Polygon)) as Polygon;             Console.WriteLine("Polygon Name : " + shape.Name);             Polygon myPolygon = new Polygon();             myPolygon.Stroke = shape.Stroke;             myPolygon.Fill = shape.Fill;             myPolygon.StrokeThickness = 2;             Canvas.SetTop(myPolygon, e.GetPosition(dropArea).Y);              myPolygon.Points = shape.Points;             dropArea.Children.Add(myPolygon);             myPolygon.MouseRightButtonDown += new MouseButtonEventHandler(dragged_ShapeMouseDown);         }          private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e)         {              //Show Options to Delete or set Value to current Polygon         }      private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)         {             Polygon shape = e.Source as Polygon;             DragDrop.DoDragDrop(shape, shape, DragDropEffects.Copy);         }     } } 

Problem

  1. I'm using Canvas.setTop because without setting it my polygon show over the first.
  2. Here I'm setting the polygon that fix with its above polygon but it can be left or right also as shown in below screenshot.

enter image description here

2 Answers

Answers 1

SOLUTION

For Deleting shape

myPolygon.MouseLeftButtonUp += new MouseButtonEventHandler(dragged_ShapeMouseDown);  private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e) {      if (dropArea.Children.Count > 0)          dropArea.Children.Remove(sender as Polygon); } 

Answers 2

Sacha Barber has got very nice article that describe exactly what you are trying to do i think...4 steps articles up to MVVM ! have a look these step1 and step2, step3, step4 - I also used it in my own project ArchX

well, i think everything is there in my code : during onmove test the result and change the cursor. ondragend : use a HitHelper to determine where you release the mouse and return the shape his tested - then adjust the shape of the polygon regarding the hit result : below sample code - GuideLineManager

public Cursor HitTestGuide(Point p, RulerOrientation mode)     {         if (_Guides.Exists(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)))         {             return _Guides.First(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)).Cursor;          }         return Cursors.Arrow;     } 

and the onDragEnd, call to get the hit tested object

public Guideline GetSnapGuide(Point hitPoint)      {          foreach (Guideline gl in Guides)         {             if (!gl.IsDisplayed) continue;             if (gl.Info.IsSnap && !gl.Info.IsMoving)                  if (gl.IsOnGuide(hitPoint, _Container.dPicCapture))                 {                     return gl;                 }         }         return null;     } 
Read More

Wednesday, March 28, 2018

Child control handling touch event affects multi-point manipulation

Leave a Comment

I have a UserControl that must respond to TouchUp events and this sits within a Viewbox which needs to be panned and scaled with pinch manipulation. Touch events on the control are handled fine. However pinch manipulations only scale the ViewPort if both pinch points are contained entirely within either the user control or the Viewport space around it. If the pinch straddles the user control boundary then the ManipulationDelta loses one of the points and reports a scale of (1,1).

If I remove IsManipulationEnabled="True" from the control handling the TouchUp event then the scaling works but the touch event doesn’t fire.

What can I do to retain the manipulation across the ViewPort whilst also handling the touch event in the user control?

Screen Grab

Test Solution

<Window x:Class="TouchTest.MainWindow"         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"         Title="Touch Test"          Height="400"          Width="700"         ManipulationDelta="OnManipulationDelta"         ManipulationStarting="OnManipulationStarting">      <Grid Background="Transparent"            IsManipulationEnabled="True">          <Viewbox x:Name="Viewbox"                  Stretch="Uniform">              <Viewbox.RenderTransform>                 <MatrixTransform/>             </Viewbox.RenderTransform>              <Grid Width="800"                    Height="800"                    Background="LightGreen"                   IsManipulationEnabled="True"                   TouchUp="OnTouchUp">                  <TextBlock x:Name="TimeTextBlock"                             FontSize="100"                            TextAlignment="Center"                            VerticalAlignment="Center"/>              </Grid>          </Viewbox>          <TextBlock x:Name="ScaleTextBlock"                     FontSize="10"                    HorizontalAlignment="Right"                    VerticalAlignment="Bottom"/>      </Grid> </Window> 

Handlers in code-behind:

private void OnTouchUp(object sender, TouchEventArgs e) {     TimeTextBlock.Text = DateTime.Now.ToString("H:mm:ss.fff"); }  private void OnManipulationStarting(object sender, ManipulationStartingEventArgs e) {     e.ManipulationContainer = this; }  private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e) {     if (Viewbox == null)     {         return;     }      ManipulationDelta delta = e.DeltaManipulation;      ScaleTextBlock.Text = $"Delta Scale: {delta.Scale}";      MatrixTransform transform = Viewbox.RenderTransform as MatrixTransform;      if (transform == null)     {         return;     }      Matrix matrix = transform.Matrix;      Point position = ((FrameworkElement)e.ManipulationContainer).TranslatePoint(e.ManipulationOrigin, Viewbox);      position = matrix.Transform(position);      matrix = MatrixTransformations.ScaleAtPoint(matrix, delta.Scale.X, delta.Scale.Y, position);     matrix = MatrixTransformations.PreventNegativeScaling(matrix);     matrix = MatrixTransformations.Translate(matrix, delta.Translation);     matrix = MatrixTransformations.ConstrainOffset(Viewbox.RenderSize, matrix);      transform.Matrix = matrix; } 

Supporting class:

public static class MatrixTransformations {     /// <summary>     /// Prevent the transformation from being offset beyond the given size rectangle.     /// </summary>     /// <param name="size"></param>     /// <param name="matrix"></param>     /// <returns></returns>     public static Matrix ConstrainOffset(Size size, Matrix matrix)     {         double distanceBetweenViewRightEdgeAndActualWindowRight = size.Width * matrix.M11 - size.Width + matrix.OffsetX;         double distanceBetweenViewBottomEdgeAndActualWindowBottom = size.Height * matrix.M22 - size.Height + matrix.OffsetY;          if (distanceBetweenViewRightEdgeAndActualWindowRight < 0)         {             // Moved in the x-axis too far left. Snap back to limit             matrix.OffsetX -= distanceBetweenViewRightEdgeAndActualWindowRight;         }          if (distanceBetweenViewBottomEdgeAndActualWindowBottom < 0)         {             // Moved in the x-axis too far left. Snap back to limit             matrix.OffsetY -= distanceBetweenViewBottomEdgeAndActualWindowBottom;         }          // Prevent positive offset         matrix.OffsetX = Math.Min(0.0, matrix.OffsetX);         matrix.OffsetY = Math.Min(0.0, matrix.OffsetY);          return matrix;     }      /// <summary>     /// Prevent the transformation from performing a negative scale.     /// </summary>     /// <param name="matrix"></param>     /// <returns></returns>     public static Matrix PreventNegativeScaling(Matrix matrix)     {         matrix.M11 = Math.Max(1.0, matrix.M11);         matrix.M22 = Math.Max(1.0, matrix.M22);          return matrix;     }      /// <summary>     /// Translate the matrix by the given vector to providing panning.     /// </summary>     /// <param name="matrix"></param>     /// <param name="vector"></param>     /// <returns></returns>     public static Matrix Translate(Matrix matrix, Vector vector)     {         matrix.Translate(vector.X, vector.Y);         return matrix;     }      /// <summary>     /// Scale the matrix by the given X/Y factors centered at the given point.     /// </summary>     /// <param name="matrix"></param>     /// <param name="scaleX"></param>     /// <param name="scaleY"></param>     /// <param name="point"></param>     /// <returns></returns>     public static Matrix ScaleAtPoint(Matrix matrix, double scaleX, double scaleY, Point point)     {         matrix.ScaleAt(scaleX, scaleY, point.X, point.Y);         return matrix;     } } 

1 Answers

Answers 1

So, I'm not a wpf programmer. But have a suggestion/workaround which could possibly work for you.

You could code the thing as follows:

  • set IsManipulationEnabled="True" (in this case OnTouchUp isn't fired for the grid colored in LightGreen)

  • Set OnTouchUp to fire on either Viewbox x:Name="Viewbox" or the Grid above this Viewbox (rather than for the 800x800 Grid)

  • So now OnTouchUp would be fired whenever you touch anywhere in the Viewbox (not just inside the LightGreen area)

  • When OnTouchUp is now fired, just check if the co-ordinates are in the region of LightGreen box. If YES-> update the time, if no, leave the time as it is.

I understand this is a workaround. Still posted an answer, in case it could prove useful.

Read More

Monday, March 19, 2018

Preserve theme style of control while modifying the control template

Leave a Comment

I'm trying to add bind some commands to Slider.Thumb and this is how I currently do it:

<Style x:Key="BasicSliderStyle" TargetType="{x:Type customControls:ThumbDragSlider}" BasedOn="{StaticResource {x:Type Slider}}">     <Setter Property="Template">         <Setter.Value>             <ControlTemplate TargetType="{x:Type Slider}">                 <Grid>                     <Track x:Name="PART_Track">                         <Track.Thumb>                             <Thumb x:Name="Thumb">                                 <i:Interaction.Triggers>                                     <i:EventTrigger EventName="MouseEnter">                                         <command:EventToCommand Command="{Binding PositionSliderThumbMouseEnterCommand}" PassEventArgsToCommand="True"/>                                     </i:EventTrigger>                                     <i:EventTrigger EventName="DragDelta">                                         <command:EventToCommand Command="{Binding PositionThumbDragDeltaCommand}" CommandParameter="{Binding ElementName=sMovieSkipSlider}"/>                                     </i:EventTrigger>                                 </i:Interaction.Triggers>                             </Thumb>                         </Track.Thumb>                     </Track>                 </Grid>             </ControlTemplate>         </Setter.Value>     </Setter> </Style> 

The problem is that I also have a theme applied to my controls and if I use this style the style and effects from it are removed as well, is there a way to keep the current application theme style on a control while also being able to add event triggers and attach commands as show above?

P.S - Since this is a custom control that derives from Slider, this is how I set the default theme style for the slider to it

Style="{StaticResource {x:Type Slider}}" 

2 Answers

Answers 1

You can only use Triggers in the Style and not in the Template, if you want to keep the same theme for that control. That means that it is not possible in your case. What you can do is copy the entire Style of your theme and specify the trigger there.

Answers 2

You can extend your custom style. Instead of:

BasedOn="{StaticResource {x:Type Slider}}" 

do:

BasedOn="{StaticResource MyCustomSlider}" 
Read More

Tuesday, February 6, 2018

Issues using Telerik RadWindow and custom WindowManager in Caliburn Micro

Leave a Comment

I am currently working on a WPF project that utilizes Caliburn Micro and Caliburn.Micro.Telerik.

My issues are twofold. Firstly, if I create the View as a telerik:RadWindow then whenever the Show / ShowDialog method is called the window never gets displayed. If I create the view as UserControl then it will display.

Secondly TryClose() works fine without parameters but whenever I try and pass in true / false the window does not close.

For reference here are the pertinent pieces of code:

Window Manager Extensions:

public static class IWindowManagerExtensions {     /// <summary>     /// Opens an Alert modal window     /// </summary>     public static void Alert(this IWindowManager windowManager, string title, string message)     {         TelerikWindowManager.Alert(title, message);     }      /// <summary>     /// Opens an Alert modal window     /// </summary>     public static void Alert(this IWindowManager windowManager, DialogParameters dialogParameters)     {         TelerikWindowManager.Alert(dialogParameters);     }      /// <summary>     /// Opens a Confirm modal window     /// </summary>     public static void Confirm(this IWindowManager windowManager, string title, string message, System.Action onOK, System.Action onCancel = null)     {         TelerikWindowManager.Confirm(title, message, onOK, onCancel);     }      /// <summary>     /// Opens a Confirm modal window     /// </summary>     public static void Confirm(this IWindowManager windowManager, DialogParameters dialogParameters)     {         TelerikWindowManager.Confirm(dialogParameters);     }      /// <summary>     /// Opens a Prompt modal window     /// </summary>     public static void Prompt(this IWindowManager windowManager, string title, string message, string defaultPromptResultValue, Action<string> onOK)     {         TelerikWindowManager.Prompt(title, message, defaultPromptResultValue, onOK);     }      /// <summary>     /// Opens a Prompt modal window     /// </summary>     public static void Prompt(this IWindowManager windowManager, DialogParameters dialogParameters)     {         TelerikWindowManager.Prompt(dialogParameters);     } } 

Window Manager:

    public class TelerikWindowManager : WindowManager {     public override bool? ShowDialog(object rootModel, object context = null, IDictionary<string, object> settings = null)     {         var viewType = ViewLocator.LocateTypeForModelType(rootModel.GetType(), null, null);         if (typeof(RadWindow).IsAssignableFrom(viewType)             || typeof(UserControl).IsAssignableFrom(viewType))         {             var radWindow = CreateRadWindow(rootModel, true, context, settings);             radWindow.ShowDialog();             return radWindow.DialogResult;         }          return base.ShowDialog(rootModel, context, settings);     }      public override void ShowWindow(object rootModel, object context = null, IDictionary<string, object> settings = null)     {         var viewType = ViewLocator.LocateTypeForModelType(rootModel.GetType(), null, null);         if (typeof(RadWindow).IsAssignableFrom(viewType)             || typeof(UserControl).IsAssignableFrom(viewType))         {             NavigationWindow navWindow = null;              if (Application.Current != null && Application.Current.MainWindow != null)             {                 navWindow = Application.Current.MainWindow as NavigationWindow;             }              if (navWindow != null)             {                 var window = CreatePage(rootModel, context, settings);                 navWindow.Navigate(window);             }             else             {                 CreateRadWindow(rootModel, false, context, settings).Show();             }             return;         }         base.ShowWindow(rootModel, context, settings);     }       /// <summary>     /// Creates a window.     /// </summary>     /// <param name="rootModel">The view model.</param>     /// <param name="isDialog">Whethor or not the window is being shown as a dialog.</param>     /// <param name="context">The view context.</param>     /// <param name="settings">The optional popup settings.</param>     /// <returns>The window.</returns>     protected virtual RadWindow CreateRadWindow(object rootModel, bool isDialog, object context, IDictionary<string, object> settings)     {         var view = EnsureRadWindow(rootModel, ViewLocator.LocateForModel(rootModel, null, context), isDialog);         ViewModelBinder.Bind(rootModel, view, context);          var haveDisplayName = rootModel as IHaveDisplayName;         if (haveDisplayName != null && !ConventionManager.HasBinding(view, RadWindow.HeaderProperty))         {             var binding = new Binding("DisplayName") { Mode = BindingMode.TwoWay };             view.SetBinding(RadWindow.HeaderProperty, binding);         }          ApplyRadWindowSettings(view, settings);          new RadWindowConductor(rootModel, view);          return view;     }      bool ApplyRadWindowSettings(object target, IEnumerable<KeyValuePair<string, object>> settings)     {         if (settings != null)         {             var type = target.GetType();              foreach (var pair in settings)             {                 var propertyInfo = type.GetProperty(pair.Key);                  if (propertyInfo != null)                 {                     propertyInfo.SetValue(target, pair.Value, null);                 }             }              return true;         }          return false;     }      /// <summary>     /// Makes sure the view is a window is is wrapped by one.     /// </summary>     /// <param name="model">The view model.</param>     /// <param name="view">The view.</param>     /// <param name="isDialog">Whethor or not the window is being shown as a dialog.</param>     /// <returns>The window.</returns>     protected virtual RadWindow EnsureRadWindow(object model, object view, bool isDialog)     {         var window = view as RadWindow;          if (window == null)         {             var contentElement = view as FrameworkElement;             if (contentElement == null)                 throw new ArgumentNullException("view");              window = new RadWindow             {                 Content = view,                 SizeToContent = true,             };              AdjustWindowAndContentSize(window, contentElement);              window.SetValue(View.IsGeneratedProperty, true);              var owner = GetActiveWindow();             if (owner != null)             {                 window.WindowStartupLocation = WindowStartupLocation.CenterOwner;                 window.Owner = owner;             }             else             {                 window.WindowStartupLocation = WindowStartupLocation.CenterScreen;             }         }         else         {             var owner = GetActiveWindow();             if (owner != null && isDialog)             {                 window.Owner = owner;             }         }          return window;     }      /// <summary>     /// Initializes Window size with values extracted by the view.     ///      /// Note:     /// The real size of the content will be smaller than provided values.     /// The form has the header (title) and border so they will take place.     ///      /// </summary>     /// <param name="window">The RadWindow</param>     /// <param name="view">The view</param>     private static void AdjustWindowAndContentSize(RadWindow window, FrameworkElement view)     {         window.MinWidth = view.MinWidth;         window.MaxWidth = view.MaxWidth;         window.Width = view.Width;         window.MinHeight = view.MinHeight;         window.MaxHeight = view.MaxHeight;         window.Height = view.Height;          // Resetting view's settings         view.Width = view.Height = Double.NaN;         view.MinWidth = view.MinHeight = 0;         view.MaxWidth = view.MaxHeight = int.MaxValue;          // Stretching content to the Window         view.VerticalAlignment = VerticalAlignment.Stretch;         view.HorizontalAlignment = HorizontalAlignment.Stretch;     }      /// <summary>     /// Infers the owner of the window.     /// </summary>     /// <returns>The owner.</returns>     protected virtual Window GetActiveWindow()     {         if (Application.Current == null)         {             return null;         }          var active = Application.Current             .Windows.OfType<Window>()             .FirstOrDefault(x => x.IsActive);          return active ?? Application.Current.MainWindow;     }      public static void Alert(string title, string message)     {         RadWindow.Alert(new DialogParameters { Header = title, Content = message });     }      public static void Alert(DialogParameters dialogParameters)     {         RadWindow.Alert(dialogParameters);     }      public static void Confirm(string title, string message, System.Action onOK, System.Action onCancel = null)     {         var dialogParameters = new DialogParameters         {             Header = title,             Content = message         };         dialogParameters.Closed += (sender, args) =>         {             var result = args.DialogResult;             if (result.HasValue && result.Value)             {                 onOK();                 return;             }              if (onCancel != null)                 onCancel();         };         Confirm(dialogParameters);     }      public static void Confirm(DialogParameters dialogParameters)     {         RadWindow.Confirm(dialogParameters);     }      public static void Prompt(string title, string message, string defaultPromptResultValue, Action<string> onOK)     {         var dialogParameters = new DialogParameters         {             Header = title,             Content = message,             DefaultPromptResultValue = defaultPromptResultValue,         };         dialogParameters.Closed += (o, args) =>         {             if (args.DialogResult.HasValue && args.DialogResult.Value)                 onOK(args.PromptResult);         };          Prompt(dialogParameters);     }      public static void Prompt(DialogParameters dialogParameters)     {         RadWindow.Prompt(dialogParameters);     }  } 

Rad Window Conductor:

internal class RadWindowConductor {     private bool deactivatingFromView;     private bool deactivateFromViewModel;     private bool actuallyClosing;     private readonly RadWindow view;     private readonly object model;      public RadWindowConductor(object model, RadWindow view)     {         this.model = model;         this.view = view;          var activatable = model as IActivate;         if (activatable != null)         {             activatable.Activate();         }          var deactivatable = model as IDeactivate;         if (deactivatable != null)         {             view.Closed += Closed;             deactivatable.Deactivated += Deactivated;         }          var guard = model as IGuardClose;         if (guard != null)         {             view.PreviewClosed += PreviewClosed;         }     }      private void Closed(object sender, EventArgs e)     {         view.Closed -= Closed;         view.PreviewClosed -= PreviewClosed;          if (deactivateFromViewModel)         {             return;         }          var deactivatable = (IDeactivate)model;          deactivatingFromView = true;         deactivatable.Deactivate(true);         deactivatingFromView = false;     }      private void Deactivated(object sender, DeactivationEventArgs e)     {         if (!e.WasClosed)         {             return;         }          ((IDeactivate)model).Deactivated -= Deactivated;          if (deactivatingFromView)         {             return;         }          deactivateFromViewModel = true;         actuallyClosing = true;         view.Close();         actuallyClosing = false;         deactivateFromViewModel = false;     }      private void PreviewClosed(object sender, WindowPreviewClosedEventArgs e)     {         if (e.Cancel == true)         {             return;         }          var guard = (IGuardClose)model;          if (actuallyClosing)         {             actuallyClosing = false;             return;         }          bool runningAsync = false, shouldEnd = false;          guard.CanClose(canClose =>         {             Execute.OnUIThread(() =>             {                 if (runningAsync && canClose)                 {                     actuallyClosing = true;                     view.Close();                 }                 else                 {                     e.Cancel = !canClose;                 }                  shouldEnd = true;             });         });          if (shouldEnd)         {             return;         }          e.Cancel = true;         runningAsync = true;     } } 

New User View Model:

    [Export, PartCreationPolicy(CreationPolicy.NonShared)] [ExportController("NewUserViewModel")] public class NewUserViewModel : FeatureWindowBase {     #region Fields     private User _creatingUser;     private User _userToAdd;     #endregion      #region Properties      public bool IsOpen;      public User UserToAdd     {         get         {             return _userToAdd;          }         set         {             _userToAdd = value;              NotifyOfPropertyChange(() => UserToAdd);         }     }      public IEnumerable<Entity> AddedUsers => new List<Entity>() { UserToAdd };      #endregion       #region Constructors      [ImportingConstructor]     public NewUserViewModel(IWindowManager windowManager,         IEventAggregator eventAggregator,         IEntityManagerProvider<BearPawEntities> entityManagerProvider,         IGlobalCache globalCache) :         base(windowManager, eventAggregator, entityManagerProvider, globalCache)     {     }      #endregion      protected override void OnViewLoaded(object view)     {         base.OnViewLoaded(view);          // un-comment the following if you want to use the Global Cache         SetupGlobalCache<User>(Manager);         _creatingUser = Manager.Users.FirstOrDefault(u => u.UserName ==                                                  Manager.AuthenticationContext.Principal.Identity                                                      .Name);          UserToAdd = new User()         {             CreatedBy = _creatingUser,             CreatedDate = DateTime.Now,             ModifiedBy = _creatingUser,             ModifiedDate = DateTime.Now         };          DisplayName = "Add New User";         IsOpen = true;     }      #region Methods       public async Task CreateUser()     {         try         {              var newAuth = new UserAuthentication()             {                 Password = Security.CreateSaltedPasswordForNewUser("LetMeIn"),                 Salt = Security.LastSalt,                 CreatedBy = _creatingUser,                 CreatedDate = DateTime.Now,                 ModifiedBy = _creatingUser,                 ModifiedDate = DateTime.Now             };               Security.ClearLastSalt();              Manager.AddEntity(newAuth);             UserToAdd.UserAuthentication = newAuth;              Manager.AddEntity(UserToAdd);              var saveResponse = await Manager.TrySaveChangesAsync();              if (saveResponse.Ok)             {                 TryClose(true);             }         }         catch (Exception)         {             throw;         }     }      #endregion  } 

Finally, from our App Bootstrapper:

        protected override void Configure()     {         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("xunit.*");         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("BearPaw.Client.*");         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("BearPaw.Clients.*");         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("Caliburn.*");         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("JetBrains.*");         IdeaBlade.Core.Composition.CompositionHost.IgnorePatterns.Add("FluentAssertions.*");          var conventions = new RegistrationBuilder();         conventions.ForTypesDerivedFrom<IBearPawFeature>()             .Export()             .SetCreationPolicy(CreationPolicy.NonShared);           _container = new CompositionContainer(             new AggregateCatalog(                 AssemblySource.Instance.Select(x=> new AssemblyCatalog(x, conventions)).OfType<ComposablePartCatalog>()                 )             );          var batch = new CompositionBatch();          batch.AddExportedValue<IWindowManager>(new TelerikWindowManager());         batch.AddExportedValue<IEventAggregator>(new EventAggregator());         batch.AddExportedValue<IEntityManagerProvider<BearPawEntities>>(new MainEntityManagerProvider());         batch.AddExportedValue<IEntityManagerProvider<BearPawReportingEntities>>(new ReportingEntityManagerProvider());         batch.AddExportedValue(_container);          // This is essential to enable Telerik's conventions         TelerikConventions.Install();          AddKeyBindingTriggers();          VisualStudio2013Palette.LoadPreset(VisualStudio2013Palette.ColorVariation.Dark);         VisualStudio2013Palette.Palette.BasicColor = Color.FromArgb(255, 77, 77, 82);           _container.Compose(batch);     } 

If anyone has any ideas on what may be up I would be super grateful.

Thanks in advance

0 Answers

Read More

Wednesday, January 10, 2018

How to integrate LDAP in WPF application that consumes WCF service

Leave a Comment

I will start by describing how my application works today without LDAP. I have WPF application that consumes WCF services (authentication windows or UserName depends on users choice). This services allows communication with database.

I display to user a "Login screen" in order to allow him set her "user name" and "password" then application connects to service and consumes function that checks if UserName and Password exist in database. (see img below) enter image description here

Now I need also to integrate LDAP for authenticating user accounts against their existing systems instead of having to create another login account.

I'm bit ignorant about LDAP and confused about many things. Please excuse the possible use of wrong terminology.

I googled but I still don't have answers of many questions.

1- What is the relation between users that exist in my database table "User" and profiles that I should be created in LDAP ?

2- What is the check I should do to allow user come from LDAP to access to my application and use all functionnalities of my service ?

3- Should I have service type "LDAP" like other authentications types I have today in my application ("Windows" and "UserName") ?

4- If I want to update my application architecture described in picture above where should I add LDAP ?

1 Answers

Answers 1

Let me tell you about my experience in LDAP and Authenticate users on LDAP or DB,

I also implemented a service named Auth.svc, this service contains a method named AuthenticateAndAuthorizedUser , this is transparent for user which came from LDAP or anywhere.

1- In the other words I have a table named Users which hold users infos and one more field named ExternalPath foreign key, if it is null then UserName is in DB otherwise it is came from UserDirectory.

2- You have to hold LDAP address (in my case LDAP addresses are in ExternalPath table), All LDAP addresses are on port 389 commonly.

3- Authenticate User if is not found(with Username and Password) then Verify it over LDAP address.

4- Let me share my DB schema and Authenticate Method.

enter image description here

ExternalPath field specify user is from LDAP or not.

5- Define LDAP server and User...

enter image description here

6- While adding new user you can define LDAP for user (if you select LDAP address then don't need to get password from user)

7- But last thing is Authenticating user on LDAP and DB.

Authenticate Method is something like:

User userLogin = User.Login<User>(username, password, ConnectionString, LogFile); if (userLogin != null)     return InitiateToken(userLogin, sourceApp, sourceAddress, userIpAddress); else//Check it's LDAP path {     User user = new User(ConnectionString, LogFile).GetUser(username);     if (user != null && user.ExternalPath != null)     {         LDAPSpecification spec = new LDAPSpecification         {             UserName = username,             Password = password,             Path = user.ExternalPath.Path,             Domain = user.ExternalPath.Domain         };         bool isAthenticatedOnLDAP = LDAPAuthenticateUser(spec);      } } 

If userLogin does not exist in DB by entered UserName and Pass then we should authenticated it over related LDAP address.

First find User and Get it's ExternalPath if not null means User is on LDAP.

so the LDAPAuthenticateUser method is :

public bool LDAPAuthenticateUser(LDAPSpecification spec) {     string pathDomain = string.Format("LDAP://{0}", spec.Path);     if (!string.IsNullOrEmpty(spec.Domain))         pathDomain += string.Format("/{0}", spec.Domain);     DirectoryEntry entry = new DirectoryEntry(pathDomain, spec.UserName, spec.Password, AuthenticationTypes.Secure);     try     {         //Bind to the native AdsObject to force authentication.         object obj = entry.NativeObject;         DirectorySearcher search = new DirectorySearcher(entry);          search.Filter = "(SAMAccountName=" + spec.UserName + ")";         search.PropertiesToLoad.Add("cn");         SearchResult result = search.FindOne();         if (null == result)         {             return false;         }     }     catch (Exception ex)     {         Logging.Log(LoggingMode.Error, "Error authenticating user on LDAP , PATH:{0} , UserName:{1}, EXP:{2}", pathDomain, spec.UserName, ex.ToString());         return false;     }     return true; } 

If exception raised in LDAPAuthenticateUser means User does not exist in User Directory.

Hope will help you.

Read More

Thursday, December 28, 2017

DatePicker throws exception on changing Month

Leave a Comment

Changing the month of a DatePicker throws this exception:

System.Windows.Automation.ElementNotAvailableException: 'Element does not exist or it is virtualized; use VirtualizedItem Pattern if it is supported.'

The Stack Trace:

at MS.Internal.Automation.ElementUtil.Invoke(AutomationPeer peer, DispatcherOperationCallback work, Object arg) at MS.Internal.Automation.ElementProxy.GetPropertyValue(Int32 property)

I created a simple project with only one DatePicker on the main window and it gives the same exception.

<DatePicker x:Name="datePicker1" Width="150" /> 

.NET Framework version: 4.6

I found the same problem in a 6 years old question, but no answer till now!

Edit:

I tried different .NET Framework versions: 4.5, 4.6.1, and the problem still the same.

5 Answers

Answers 1

If you look on the microsoft documentation it says:

This exception can be raised if the element was in a dialog box that was closed, or an application that was closed or terminated.

Could it be possible that you're closing the window on a "change month" event?

Answers 2

It is difficult to reproduce your issue. The next suggestions may help you:

  • another process may affect to your program. Do you use utilities like Snoop or UISpy?

  • your problem may be related to low-performance hardware or vendor software bug. See here answer for resolving this issue

  • your problem may be related to rendering a copy of UI-control which doesn't exist for some reasons. See this discussion for more details

Answers 3

The exception appears to depend on the Tablet PC Input Service being enabled. If I had to guess, the error occurs in UI Automation code that only runs when pen-based input is available (and possibly touch-based input). I've seen that service induce undesirable side effects in WPF applications before, and most of those issues were also related to UI Automation.

Since this appears to be a "first chance" exception (it gets handled somewhere in the framework), the only people should notice are developers who have their IDE configured to break on all exceptions (as opposed to only unhandled exceptions). If that is indeed the case, and if those developers are not actually using the pen or touch input capabilities, it might be easiest to just disable the Tablet PC Input Service and move on with your lives.

Alternatively, you could configure Visual Studio to not break on that particular exception type, which only pertains to UI Automation anyway.

Since things are pretty slow at the office this week, I will spend some additional time looking into this. If I can find a code-based solution, I will update my answer here. But from the look of it, the UI is constructed almost entirely programmatically, so this probably isn't something you can fix with a simple custom template.

Answers 4

(As I needed some diversion) I tried to do some research on your case and could reproduce the mentioned exception. Enabling .NET Framework source stepping and anything else I could find I was able to pinpoint the exception to the Invoke method of the ElementUtil class in the PresentationCore.dll. The corresponding code of the method looks like this:

internal static object Invoke(AutomationPeer peer, DispatcherOperationCallback work, object arg) {     Dispatcher dispatcher = peer.Dispatcher;      // Null dispatcher likely means the visual is in bad shape!     if( dispatcher == null )     {         throw new ElementNotAvailableException();     }      Exception remoteException = null;     bool completed = false;      object retVal = dispatcher.Invoke(                     DispatcherPriority.Send,         TimeSpan.FromMinutes(3),         (DispatcherOperationCallback) delegate(object unused)         {             try             {                 return work(arg);             }             catch(Exception e)             {                 remoteException = e;                 return null;             }             catch        //for non-CLS Compliant exceptions             {                 remoteException = null;                 return null;             }             finally             {                 completed = true;             }          },         null);      if(completed)     {         if(remoteException != null)         {             throw remoteException;         }     }     else     {         bool dispatcherInShutdown = dispatcher.HasShutdownStarted;          if(dispatcherInShutdown)         {             throw new InvalidOperationException(SR.Get(SRID.AutomationDispatcherShutdown));         }         else         {             throw new TimeoutException(SR.Get(SRID.AutomationTimeout));         }     }      return retVal;  } 

Taking this code into consideration the (in my opinion) only possible reason is, that the specified dispatcher is null. Altough I find the comment

// Null dispatcher likely means the visual is in bad shape!

funny, I have actually no idea why this is the case. I tired to debugging that fact but was unable to get any meaningful information. Only following stacktrace (which opened my eyes again about what is going on if we "just click a button"):

PresentationCore.dll!MS.Internal.Automation.ElementUtil.Invoke(System.Windows.Automation.Peers.AutomationPeer peer, System.Windows.Threading.DispatcherOperationCallback work, object arg) PresentationCore.dll!MS.Internal.Automation.ElementProxy.GetPropertyValue(int property) [Native to Managed Transition] UIAutomationCore.dll!ProviderCallouts::RawGetPropertyValue(struct IRawElementProviderSimple *,int,struct tagVARIANT *) UIAutomationCore.dll!ProviderCallouts::GetPropertyValue(struct IRawElementProviderSimple *,unsigned short,class ProviderEntryPoint *,int,struct tagVARIANT *) UIAutomationCore.dll!InProcClientAPIStub::GetPropertyValue(char *) UIAutomationCore.dll!InProcClientAPIStub::InvokeInProcAPI(struct ITargetContextInvoker *,enum Protocol_MethodId,...) UIAutomationCore.dll!AccessibleProxy::IsControl(struct IRawElementProviderFragment *,struct ITargetContextInvoker *) UIAutomationCore.dll!AccessibleProxy::NormalizeUpwards(struct IRawElementProviderFragment *,struct ITargetContextInvoker *,struct IRawElementProviderFragment * *) UIAutomationCore.dll![thunk]:EditProxy::Release`adjustor{32}' (void) UIAutomationCore.dll!_UiaReturnRawElementProvider@16() [Managed to Native Transition] UIAutomationProvider.dll!MS.Internal.Automation.UiaCoreProviderApi.UiaReturnRawElementProvider(System.IntPtr hwnd = 0x000406ce, System.IntPtr wParam = 0xffffffff, System.IntPtr lParam = 0x00000149, System.Windows.Automation.Provider.IRawElementProviderSimple el = {MS.Internal.Automation.ElementProxy}) UIAutomationProvider.dll!System.Windows.Automation.Provider.AutomationInteropProvider.ReturnRawElementProvider(System.IntPtr hwnd = 0x000406ce, System.IntPtr wParam = 0xffffffff, System.IntPtr lParam = 0x00000149, System.Windows.Automation.Provider.IRawElementProviderSimple el = {MS.Internal.Automation.ElementProxy}) PresentationCore.dll!System.Windows.Interop.HwndTarget.CriticalHandleWMGetobject(System.IntPtr wparam, System.IntPtr lparam, System.Windows.Media.Visual root, System.IntPtr handle) PresentationCore.dll!System.Windows.Interop.HwndTarget.HandleMessage(MS.Internal.Interop.WindowMessage msg, System.IntPtr wparam, System.IntPtr lparam) PresentationCore.dll!System.Windows.Interop.HwndSource.HwndTargetFilterMessage(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled = false) WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd = 0x000406ce, int msg = 0x0000003d, System.IntPtr wParam = 0xffffffff, System.IntPtr lParam = 0x00000149, ref bool handled = false) WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler = null) WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd = 0x000406ce, int msg = 0x0000003d, System.IntPtr wParam = 0xffffffff, System.IntPtr lParam = 0x00000149) [Native to Managed Transition] user32.dll!__InternalCallWinProc@20() user32.dll!InternalCallWinProc() user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,void *,struct HWND__ *,enum _WM_VALUE,unsigned int,long,void *,int) user32.dll!_DispatchClientMessage@24() user32.dll!___fnDWORD@4() ntdll.dll!_KiUserCallbackDispatcher@12() user32.dll!_SendMessageTimeoutW@28() oleacc.dll!NativeIAccessibleFromWindow(unsigned long,unsigned long,struct HWND__ *,unsigned long,struct _GUID const &,void * *) oleacc.dll!_ORIGINAL_AccessibleObjectFromWindow@24() oleacc.dll!_AccessibleObjectFromWindow@16() oleacc.dll!_AccessibleObjectFromEvent@20() oleacc.dll!_EXTERNAL_AccessibleObjectFromEvent@20() msctf.dll!_AccessibleObjectFromEvent@20() msctf.dll!CThreadInputMgr::OnAccFocusEvent() msctf.dll!WinEventProc() user32.dll!___ClientCallWinEventProc@4() ntdll.dll!_KiUserCallbackDispatcher@12() [Managed to Native Transition] UIAutomationProvider.dll!MS.Internal.Automation.UiaCoreProviderApi.UiaRaiseAutomationEvent(System.Windows.Automation.Provider.IRawElementProviderSimple provider = {MS.Internal.Automation.ElementProxy}, int eventId = 0x00004e25) UIAutomationProvider.dll!System.Windows.Automation.Provider.AutomationInteropProvider.RaiseAutomationEvent(System.Windows.Automation.AutomationEvent eventId = {System.Windows.Automation.AutomationEvent}, System.Windows.Automation.Provider.IRawElementProviderSimple provider = {MS.Internal.Automation.ElementProxy}, System.Windows.Automation.AutomationEventArgs e = {System.Windows.Automation.AutomationEventArgs}) PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.RaiseAutomationEvent(System.Windows.Automation.Peers.AutomationEvents eventId) PresentationCore.dll!System.Windows.Automation.Peers.AutomationPeer.RaiseFocusChangedEventHelper(System.Windows.IInputElement newFocus) PresentationCore.dll!System.Windows.Input.KeyboardDevice.ChangeFocus(System.Windows.DependencyObject focus, int timestamp) PresentationCore.dll!System.Windows.Input.KeyboardDevice.TryChangeFocus(System.Windows.DependencyObject newFocus, System.Windows.Input.IKeyboardInputProvider keyboardInputProvider, bool askOld, bool askNew, bool forceToNullIfFailed) PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.DependencyObject focus, bool askOld, bool askNew, bool forceToNullIfFailed) PresentationCore.dll!System.Windows.Input.KeyboardDevice.Focus(System.Windows.IInputElement element) PresentationCore.dll!System.Windows.UIElement.Focus() PresentationFramework.dll!System.Windows.Input.KeyboardNavigation.Navigate(System.Windows.DependencyObject currentElement, System.Windows.Input.TraversalRequest request, System.Windows.Input.ModifierKeys modifierKeys, System.Windows.DependencyObject firstElement) PresentationFramework.dll!System.Windows.FrameworkElement.MoveFocus(System.Windows.Input.TraversalRequest request) PresentationFramework.dll!System.Windows.Controls.Primitives.CalendarItem.FocusDate(System.DateTime date) PresentationFramework.dll!System.Windows.Controls.Calendar.OnCalendarButtonPressed(System.Windows.Controls.Primitives.CalendarButton b, bool switchDisplayMode) PresentationFramework.dll!System.Windows.Controls.Primitives.CalendarItem.Month_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e) PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source = {System.Windows.Controls.Primitives.CalendarButton}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseButtonEventArgs}, bool reRaised = true) PresentationCore.dll!System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject sender = {System.Windows.Controls.Primitives.CalendarButton}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseButtonEventArgs}, System.Windows.RoutedEvent newEvent) PresentationCore.dll!System.Windows.UIElement.OnMouseUpThunk(object sender, System.Windows.Input.MouseButtonEventArgs e) PresentationCore.dll!System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate genericHandler, object genericTarget) PresentationCore.dll!System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate handler, object target) PresentationCore.dll!System.Windows.RoutedEventHandlerInfo.InvokeHandler(object target, System.Windows.RoutedEventArgs routedEventArgs) PresentationCore.dll!System.Windows.EventRoute.InvokeHandlersImpl(object source = {System.Windows.Shapes.Rectangle}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseButtonEventArgs}, bool reRaised = false) PresentationCore.dll!System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject sender = {System.Windows.Shapes.Rectangle}, System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseButtonEventArgs}) PresentationCore.dll!System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs args = {System.Windows.Input.MouseButtonEventArgs}) PresentationCore.dll!System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs args, bool trusted) PresentationCore.dll!System.Windows.Input.InputManager.ProcessStagingArea() PresentationCore.dll!System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs input) PresentationCore.dll!System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport inputReport) PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.ReportInput(System.IntPtr hwnd, System.Windows.Input.InputMode mode, int timestamp, System.Windows.Input.RawMouseActions actions, int x, int y, int wheel) PresentationCore.dll!System.Windows.Interop.HwndMouseInputProvider.FilterMessage(System.IntPtr hwnd = 0x000406ce, MS.Internal.Interop.WindowMessage msg = WM_LBUTTONUP, System.IntPtr wParam = 0x00000000, System.IntPtr lParam = 0x005b0066, ref bool handled = false) PresentationCore.dll!System.Windows.Interop.HwndSource.InputFilterMessage(System.IntPtr hwnd = 0x000406ce, int msg = 0x00000202, System.IntPtr wParam = 0x00000000, System.IntPtr lParam = 0x005b0066, ref bool handled = false) WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd = 0x000406ce, int msg = 0x00000202, System.IntPtr wParam = 0x00000000, System.IntPtr lParam = 0x005b0066, ref bool handled = false) WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.TryCatchWhen(object source = {System.Windows.Threading.Dispatcher}, System.Delegate callback, object args, int numArgs, System.Delegate catchHandler = null) WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd = 0x000406ce, int msg = 0x00000202, System.IntPtr wParam = 0x00000000, System.IntPtr lParam = 0x005b0066) [Native to Managed Transition] user32.dll!__InternalCallWinProc@20() user32.dll!InternalCallWinProc() user32.dll!UserCallWinProcCheckWow(struct _ACTIVATION_CONTEXT *,void *,struct HWND__ *,enum _WM_VALUE,unsigned int,long,void *,int) user32.dll!_DispatchMessageWorker@8() user32.dll!_DispatchMessageW@4() WindowsBase.ni.dll!69d4936c() [Frames below may be incorrect and/or missing, native debugger attempting to walk managed call stack] [Managed to Native Transition] WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame = {System.Windows.Threading.DispatcherFrame}) WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame frame) PresentationFramework.dll!System.Windows.Application.RunDispatcher(object ignore) PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) PresentationFramework.dll!System.Windows.Application.Run(System.Windows.Window window) PresentationFramework.dll!System.Windows.Application.Run() WpfApp1.exe!WpfApp1.App.Main() [Native to Managed Transition] mscoreei.dll!__CorExeMain@0() mscoree.dll!_ShellShim__CorExeMain@0() mscoree.dll!__CorExeMain_Exported@0() ntdll.dll!__RtlUserThreadStart() ntdll.dll!__RtlUserThreadStart@8() 

Just for fun here ist the same stacktrace as above in graphical form: Stacktrace

So my conslusion is that...

Answers 5

A possible work around would be to Try, Catch, Finally the UIAnimation exception and not raise any events (message boxes, error logs) when it occurs. Just let the code continue on as if nothing happened.

Read More

Tuesday, December 26, 2017

How do I use PresentationCore in a WebAPI hosted on Azure?

Leave a Comment

I have developed a "simple" testcase:

[HttpPost] [Route("GetImage")] public HttpResponseMessage GetImage() {     try     {         int bmpX = 50;         int bmpY = 50;         DrawingVisual drawingVisual = new DrawingVisual();         var dc = drawingVisual.RenderOpen();         dc.DrawRectangle(Brushes.Green, new Pen(Brushes.Green, 3), new System.Windows.Rect(0, 0, bmpX, bmpY));         dc.DrawLine(new Pen(Brushes.Red, 2.0), new System.Windows.Point(0, 0), new System.Windows.Point(bmpX, bmpY));         dc.DrawLine(new Pen(Brushes.Red, 2.0), new System.Windows.Point(0, bmpY), new System.Windows.Point(bmpX, 0));         dc.Close();         var bmp = new RenderTargetBitmap(bmpX, bmpY, 96, 96, PixelFormats.Pbgra32);         bmp.Render(drawingVisual);         var encoder = new PngBitmapEncoder();         encoder.Frames.Add(BitmapFrame.Create(bmp));         MemoryStream memoryStream = new MemoryStream();         encoder.Save(memoryStream);         HttpResponseMessage httpResponseMessage = new HttpResponseMessage();         httpResponseMessage.Content = new ByteArrayContent(memoryStream.ToArray());         httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");         httpResponseMessage.StatusCode = HttpStatusCode.OK;         return httpResponseMessage;     }     catch (Exception ex)     {         var message = Request.CreateResponse(HttpStatusCode.Created, ex.ToString());         return message;     } } 

This is a function inside my ASP.Net WebAPI project, as part of a Controller (ValuesController as it happens, so adding this to a default project should reproduce the problem easily enough). If I deploy this to Azure and run it locally, then invoke both from Fiddler, the local one works as expected and returns a red X on a green background, but the Azure one returns a blank image.

If I use GDI (System.Drawing.Bitmap) then it works OK, even from Azure. Unfortunately this isn't a solution; I'm porting an already-written application from desktop to an Azure API service and the PresentationCore code is extensive and would take too long to convert to GDI.

Edit: if anyone has a working Azure/Web API/PresentationCore application that I could pick through, that could be very helpful.

0 Answers

Read More

Friday, December 22, 2017

Pause/prevent animation for a checkbox control

Leave a Comment

I have a checkbox substituting a switch-like control.

enter image description here

enter image description here

It works great. The only problem is that this checkbox initial mode can be either true or false. For false - no problem, but if it's true, then when the view is loaded, you immediately see the animation of the switch moving.

I want to prevent that. Is there anyway to do so?

Here's the relevant XAML:

<CheckBox Style="{StaticResource MySwitch}"  IsChecked="{Binding ExplicitIncludeMode}" ></CheckBox>  <Style x:Key="MySwitch" TargetType="{x:Type CheckBox}">     <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>     <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>     <Setter Property="Template">         <Setter.Value>             <ControlTemplate TargetType="{x:Type CheckBox}">                 <ControlTemplate.Resources>                     <Storyboard x:Key="OnChecking">                         <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">                             <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="55"/>                         </DoubleAnimationUsingKeyFrames>                     </Storyboard>                     <Storyboard x:Key="OnUnchecking">                         <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">                             <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0"/>                         </DoubleAnimationUsingKeyFrames>                         <ThicknessAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(FrameworkElement.Margin)">                             <SplineThicknessKeyFrame KeyTime="00:00:00.3000000" Value="1,1,1,1"/>                         </ThicknessAnimationUsingKeyFrames>                     </Storyboard>                 </ControlTemplate.Resources>                  <DockPanel x:Name="dockPanel">                     <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" ContentTemplate="{TemplateBinding ContentTemplate}" RecognizesAccessKey="True" VerticalAlignment="Center"/>                     <Border BorderBrush="LightGray" BorderThickness="1" Margin="5,5,0,5">                         <Grid  Width="110" Background="GhostWhite">                             <TextBlock Text="Included" TextWrapping="Wrap" FontWeight="Medium" FontSize="12" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,3,0" Foreground="#FF00AFC4"/>                             <TextBlock HorizontalAlignment="Left" Margin="2,0,0,0" FontSize="12" FontWeight="Bold" Text="Excluded" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#FFE4424D"/>                             <Border HorizontalAlignment="Left" x:Name="slider" Width="55" BorderThickness="1,1,1,1" CornerRadius="3,3,3,3" RenderTransformOrigin="0.5,0.5" Margin="1,1,1,1">                                 <Border.RenderTransform>                                     <TransformGroup>                                         <ScaleTransform ScaleX="1" ScaleY="1"/>                                         <SkewTransform AngleX="0" AngleY="0"/>                                         <RotateTransform Angle="0"/>                                         <TranslateTransform X="0" Y="0"/>                                     </TransformGroup>                                 </Border.RenderTransform>                                 <Border.BorderBrush>                                     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">                                         <GradientStop Color="WhiteSmoke" Offset="0"/>                                         <GradientStop Color="#FFFFFFFF" Offset="1"/>                                     </LinearGradientBrush>                                 </Border.BorderBrush>                                 <Border.Background>                                     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">                                         <GradientStop x:Name="grdColor" Color="#FF00AFC4" Offset="1"/>                                         <GradientStop Color="#092E3E" Offset="0"/>                                     </LinearGradientBrush>                                 </Border.Background>                             </Border>                         </Grid>                     </Border>                 </DockPanel>                  <ControlTemplate.Triggers>                     <MultiTrigger>                         <MultiTrigger.Conditions>                             <Condition Property="IsChecked" Value="True"/>                             <Condition Property="IsPressed" Value="True"/>                         </MultiTrigger.Conditions>                          <MultiTrigger.ExitActions>                             <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard"/>                         </MultiTrigger.ExitActions>                         <MultiTrigger.EnterActions>                             <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard"/>                         </MultiTrigger.EnterActions>                     </MultiTrigger>                     <Trigger Property="IsEnabled" Value="False">                         <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>                     </Trigger>                 </ControlTemplate.Triggers>             </ControlTemplate>         </Setter.Value>     </Setter>     <Setter Property="Width" Value="118"></Setter>     <Setter Property="Height" Value="39"></Setter>  </Style> 

This is the way I initialize the view + viewmodel:

// ctor of view (tab) public MonitoredExtensions() {     InitializeComponent();     DataContext = new MonitoredExtensionsViewModel(); }  // ctor of viewmodel public MonitoredExtensionsViewModel() {      ...      ExplicitIncludeMode = true/false;      ... } 

1 Answers

Answers 1

Found 1 way to do this.

Turns out you can bind the initial X location of the switch/slider. So I binded it to a property in the ViewModel, and updated it.

Changes to XAML:

<TranslateTransform X="{Binding InitialPosition}" Y="0"/> 

Ctor of View:

public MonitoredExtensions() {     InitializeComponent();     DataContext = new MonitoredExtensionsViewModel(); } 

Ctor of ViewModel:

public MonitoredExtensionsViewModel() {      ...      ExplicitIncludeMode = true/false;      InitialPosition = (ExplicitIncludeMode) ? 55 : 0;      ... } 

More from the ViewModel:

public Double InitialPosition { get; set; } 

So as the view is loaded, the viewmodel is being created, and the original/initial location of the slider is calculated according to the checkbox state.

Read More