WPF Designer Extensibility: how to get the current designer zoom value? - visual-studio

I created a simple custom control with design-time support like the one described here
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.ComponentModel;
namespace CustomControlLibrary
{
public class ButtonWithDesignTime : Button
{
public ButtonWithDesignTime()
{
// The GetIsInDesignMode check and the following design-time
// code are optional and shown only for demonstration.
if (DesignerProperties.GetIsInDesignMode(this))
{
Content = "Design mode active";
}
}
}
}
Now I need to know what is the zoom factor set at design time by Visual Studio, but I cannot figure out how.
Is there an event that I can listen to for finding out this? Or is there a property that could reveal this?

I'm not sure if this is the most elegant way of doing it, but this is what I came up with. This problem has been thwarting me for ages!
private Point GetScaleFactor()
{
var rootVisual = PresentationSource.FromVisual(this)?.RootVisual;
if (rootVisual != null)
{
var transformToRoot = TransformToAncestor(rootVisual);
if (transformToRoot is Transform t)
{
return new Point(t.Value.M11, t.Value.M22);
}
}
return new Point(1, 1);
}

Related

Unity WebGL - Is there a way to clear all errors on build?

I am wondering if there's a way to clear the error that pops up in the browser after the game is built?
I tried this code I found online, but it doesn't work as expected. I tried to put the script below in the Editor folder, but it didn't work as well.
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEngine;
using System.Reflection;
//using UnityEditor;
public class ClearConsole : MonoBehaviour
{
public void ClearLog()
{
var assembly = Assembly.GetAssembly(typeof(UnityEditor.Editor));
var type = assembly.GetType("UnityEditor.LogEntries");
var method = type.GetMethod("Clear");
method.Invoke(new object(), null);
}
void Update()
{
ClearLog();
}
}
#endif
Sorry for my English. Thanks in advance.

Is there a way I can add a left and right margin to the Shell tab area with Xamarin forms?

My page has a margin on the left and right when viewed on a tablet device in landscape mode:
Is there any way that I can add a left and right margin to the tab area also?
Here, the better approach will be to use Padding instead of Margin. You will see why in a while.
So, to start with the implementation - you will need to harness the power of Custom renderers.
In this specific case, we will need to inherit from ShellRenderer. Also, there are some differences for Android & for iOS - for Android, you will need to override CreateBottomNavViewAppearanceTracker and for iOS - CreateTabBarAppearanceTracker
Assuming that you have followed the recommendations and named your Shell AppShell, then the 2 classes will look like this.
Android:
using Android.Content;
using TestShellTabBarMargin;
using TestShellTabBarMargin.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(AppShell), typeof(AppShellRenderer))]
namespace TestShellTabBarMargin.Droid
{
public class AppShellRenderer : ShellRenderer
{
public AppShellRenderer(Context context)
: base(context)
{
}
protected override IShellBottomNavViewAppearanceTracker CreateBottomNavViewAppearanceTracker(ShellItem shellItem)
{
return new MarginedTabBarAppearance();
}
}
}
iOS:
using TestShellTabBarMargin;
using TestShellTabBarMargin.iOS;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(AppShell), typeof(AppShellRenderer))]
namespace TestShellTabBarMargin.iOS
{
public class AppShellRenderer : ShellRenderer
{
protected override IShellTabBarAppearanceTracker CreateTabBarAppearanceTracker()
{
return new MarginedTabBarAppearance();
}
}
}
Next, you will need to create the appearance classes and inherit from the base classes (Android - ShellBottomNavViewAppearanceTracker & iOS - ShellTabBarAppearanceTracker).
NB!: You can also implement their interfaces (Android - IShellBottomNavViewAppearanceTracker & iOS - IShellTabBarAppearanceTracker) but this way you will lose all of the styles that you have already applied and then you'll have to set them by hand.
After the classes have been subclassed, the important method is SetAppearance. ResetAppearance will also work, but it is invoked in many other cases and we need to change it only once.
Here is how it looks by default on Android:
The proper implementation is to set the left & right paddings of the bottom navigation view like this:
using Android.Support.Design.Widget;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
namespace TestShellTabBarMargin.Droid
{
public class MarginedTabBarAppearance : ShellBottomNavViewAppearanceTracker
{
public MarginedTabBarAppearance(IShellContext shellContext, ShellItem shellItem)
: base(shellContext, shellItem)
{
}
public override void SetAppearance(BottomNavigationView bottomView, IShellAppearanceElement appearance)
{
base.SetAppearance(bottomView, appearance);
bottomView.SetPadding(400, 0, 400, 0);
}
}
}
End result:
If we want to set the margins, instead of the paddings, then we can modify the layoutParams of the view like this:
public override void SetAppearance(BottomNavigationView bottomView, ShellAppearance appearance)
{
if (bottomView.LayoutParameters is LinearLayout.LayoutParams layoutParams)
{
layoutParams.SetMargins(400, 0, 400, 0);
bottomView.LayoutParameters = layoutParams;
}
}
However, here it will look like this:
You can go and try to set the parent view's Background color, but the end result will be the same and with the Padding set you won't need to try to fix what is not broken.
For iOS the base flow is the same. The important method is again SetAppearance and inside it we can modify our UITabBar.
Unfortunately, I haven't found yet the proper config yet, but I will update my answer when I do. Setting the view's/frame's margins/offsets should do the work, but I suspect that the guys from Xamarin are resetting the values after the method has been executed. I bit of tinkering and trial-and-error need to happen here.
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
namespace TestShellTabBarMargin.iOS
{
public class MarginedTabBarAppearance : ShellTabBarAppearanceTracker
{
public override void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
// Modify tab bar settings
}
}
}
Edit: Setting the items' width & positioning to centered should also work and in fact is working, but only on an iPhone (on Portrait). Like I said, I suspect that the guys from Xamarin are making some updates after our changes.
This should work, but it doesn't:
public override void SetAppearance(UITabBarController controller, ShellAppearance appearance)
{
base.SetAppearance(controller, appearance);
var tabBar = controller.TabBar;
tabBar.ItemWidth = 50;
tabBar.ItemPositioning = UITabBarItemPositioning.Centered;
}
NB: Keep in mind that you will need to properly handle orientation changes and probably the device idiom (tablet or phone). According to the returned values, you can only then update the desired offsets.
You should use TabbedPageRenderer on iOS/Android platform to change the TabBar template.
For instance, Android it could be TabLayout for Android platform and TabBar for iOS
If you meant the shell tab page the first thing you should do is to implement your own ShellRenderer on platform. After that you need to override CreateTabBarAppearanceTracker method where you'll be able to create and return your own ShellTabBarAppearanceTracker(or ShellTabLayoutAppearenceTracker for Android).
After that you implement your ShellTabBarAppearanceTracker using by IShellTabBarAppearanceTracker (for iOS).
You can do it like this guy:
-Creating ShellTabBar/LayoutAppearanceTracker

Show tooltip on hover over text

I want to create extension that allows to show custom message when I hover over a text.
E.g. "test-text" should give tooltip "OK" instead of current "ITrackin..."
I tried to follow https://learn.microsoft.com/en-us/visualstudio/extensibility/walkthrough-displaying-quickinfo-tooltips?view=vs-2019
but people are stating that it is not working and it's quite long way of doing this.
I cannot find any more docs on this. I know how to display it in on-click window/get currently selected text.
The sample send by Lance Li-MSFT was really helpful, but in order to get this working I had to spend some time.
Important steps:
Import LineAsyncQuickInfoSourceProvider.cs and LineAsyncQuickInfoSource.cs
Add reference to System.ComponentModel.Composition by add reference dialog (right click on the project name)
Get missing references by installing them using NuGet Package Manager
To initialize MEF components, you’ll need to add a new Asset to source.extension.vsixmanifest.
<Assets>
...
<Asset Type = "Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
LineAsyncQuickInfoSourceProvider.cs
It's just used to display quick info/tooltip.
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Utilities;
using System.ComponentModel.Composition;
namespace JSONExtension
{
[Export(typeof(IAsyncQuickInfoSourceProvider))]
[Name("Line Async Quick Info Provider")]
[ContentType("any")]
[Order]
internal sealed class LineAsyncQuickInfoSourceProvider : IAsyncQuickInfoSourceProvider
{
public IAsyncQuickInfoSource TryCreateQuickInfoSource(ITextBuffer textBuffer) //creates instance of LineAsyncQuickInfoSource for displaying Quick Info
{
return textBuffer.Properties.GetOrCreateSingletonProperty(() => new LineAsyncQuickInfoSource(textBuffer)); //this ensures only one instance per textbuffer is created
}
}
}
LineAsyncQuickInfoSource.cs
Here you can customize what you want to display.
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Adornments;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace JSONExtension
{
internal sealed class LineAsyncQuickInfoSource : IAsyncQuickInfoSource
{
private ITextBuffer _textBuffer;
public LineAsyncQuickInfoSource(ITextBuffer textBuffer)
{
_textBuffer = textBuffer;
}
// This is called on a background thread.
public Task<QuickInfoItem> GetQuickInfoItemAsync(IAsyncQuickInfoSession session, CancellationToken cancellationToken)
{
var triggerPoint = session.GetTriggerPoint(_textBuffer.CurrentSnapshot);
if (triggerPoint != null)
{
var line = triggerPoint.Value.GetContainingLine();
var lineSpan = _textBuffer.CurrentSnapshot.CreateTrackingSpan(line.Extent, SpanTrackingMode.EdgeInclusive);
var text = triggerPoint.Value.GetContainingLine().GetText(); //get whole line of current cursor pos
ContainerElement dataElm = new ContainerElement(
ContainerElementStyle.Stacked,
new ClassifiedTextElement(
new ClassifiedTextRun(PredefinedClassificationTypeNames.Keyword, "MESSAGE TO EDIT: " + text.ToString())
));
return Task.FromResult(new QuickInfoItem(lineSpan, dataElm)); //add custom text from above to Quick Info
}
return Task.FromResult<QuickInfoItem>(null); //do not add anything to Quick Info
}
public void Dispose()
{
// This provider does not perform any cleanup.
}
}
}

Trouble disaplying custom section in Umbraco 7.6

I am trying to build a new section in Umbraco 7.6.
I had this working the 'old' way that use the tree controller extending from BaseTree but it was very ugly.
I'm now trying to do it using TreeController. I have followed the tutorials by:
Kevin Giszewski (https://github.com/kgiszewski/LearnUmbraco7/blob/master/Chapter%2016%20-%20Custom%20Sections%2C%20Trees%20and%20Actions/01%20-%20Create%20a%20Section.md)
and another by Tim Geyssens (https://github.com/TimGeyssens/UmbracoAngularBackofficePages)
but all I'm getting is an empty section without the tree and just with the title:
The controllers are not even hit on debugging, no console errors, no 500 errors, all compiles fine too.
Here's my code:
trees.config:
<add initialize="true" sortOrder="0" alias="UmbracoBookshelfTree" application="UmbracoBookshelf" title="Umbraco Bookshelf" iconClosed="icon-folder"
iconOpen="icon-folder-open" type="UmbracoBookshelf.Controllers.UmbracoBookshelfTreeController, MyWebsite.Backoffice"/>
applications.config:
<add alias="UmbracoBookshelf" name="Umbraco Bookshelf" icon="icon-globe-inverted-america" sortOrder="5"/>
Section:
using umbraco.businesslogic;
using umbraco.interfaces;
namespace UmbracoBookshelf.Applications
{
[Application("UmbracoBookshelf", "Umbraco Bookshelf", "icon-globe-inverted-america", 5)]
public class UmbracoBookshelfApplication : IApplication
{
}
}
Tree controller:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web;
using umbraco;
using umbraco.BusinessLogic.Actions;
using Umbraco.Core;
using Umbraco.Web.Models.Trees;
using Umbraco.Web.Mvc;
using Umbraco.Web.Trees;
namespace UmbracoBookshelf.Controllers
{
[PluginController("UmbracoBookshelf")]
[Umbraco.Web.Trees.Tree("UmbracoBookshelf", "UmbracoBookshelfTree", "Umbraco Bookshelf", iconClosed: "icon-folder")]
public class UmbracoBookshelfTreeController : TreeController
{
protected override Umbraco.Web.Models.Trees.MenuItemCollection GetMenuForNode(string id, System.Net.Http.Formatting.FormDataCollection queryStrings)
{
var menu = new MenuItemCollection();
if (id == Constants.System.Root.ToInvariantString())
{
// root actions
menu.Items.Add<CreateChildEntity, ActionNew>(ui.Text("actions", ActionNew.Instance.Alias));
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
return menu;
}
else
{
//menu.DefaultMenuAlias = ActionDelete.Instance.Alias;
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
}
return menu;
}
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
{
var nodes = new TreeNodeCollection();
nodes.Add(CreateTreeNode("123", "456", queryStrings, "Some name to be shown"));
nodes.Add(CreateTreeNode("789", "456", queryStrings, "Some other name to be shown"));
return nodes;
}
}
}
It's pretty simple, what could wrong here?
I see the difference between my example and yours is , MyWebsite.Backoffice in trees.config I suggest to remove it.
<add initialize="true" sortOrder="0" alias="UmbracoBookshelfTree" application="UmbracoBookshelf" title="Umbraco Bookshelf" iconClosed="icon-folder"
iconOpen="icon-folder-open" type="UmbracoBookshelf.Controllers.UmbracoBookshelfTreeController"/>
I was running it via VS Code and IIS Express.
Tip: I found that using the code I mentioned above automatically adds App_Code to the config key and became like the following:
<add initialize="true" sortOrder="0" alias="UmbracoBookshelfTree" application="UmbracoBookshelf" title="Umbraco Bookshelf" iconClosed="icon-folder"
iconOpen="icon-folder-open" type="UmbracoBookshelf.Controllers.UmbracoBookshelfTreeController, App_Code"/>

LINQ not working on IEnumerable

I'm using Autofac (I've registered the base nuget package in a console app) and want to take a look at a list of registrations.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autofac;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// First, create your application-level defaults using a standard
// ContainerBuilder, just as you are used to.
var builder = new ContainerBuilder();
var appContainer = builder.Build();
appContainer.ComponentRegistry.Registrations.Where(x => true);
}
}
}
The problem is the line
appContainer.ComponentRegistry.Registrations.Where(x => true);
Here intellisense is not giving me the Where linq method however it does compile as far as I can tell without any warnings, errors in messages.
I tried this further down
IEnumerable<string> list = new List<string>();
list.Where(x => true);
And intellisense is working correctly and giving me all the standard list methods.
I've tried this in a few different apps from scratch and I'm getting the same behaviour.
Any ideas as to whats going on?
EDIT:
The following works and shows correctly in intellisense
IEnumerable<IComponentRegistration> test = new List<IComponentRegistration>();
test.Where(x => true);
I'm using
<package id="Autofac" version="3.0.1" targetFramework="net45" /> from nuget.
and hovering over the ComponentRegistrations gives
and in this case scope is defined as
ILifetimeScope _scope;
However I get the same thing if i try directly off this
var builder = new ContainerBuilder();
var appContainer = builder.Build();
appContainer.ComponentRegistry.Registrations.Where(x => true);
Also IComponentRegistry is defined as (in Autofac)
public interface IComponentRegistry : IDisposable
{
...
IEnumerable<IComponentRegistration> Registrations { get; }
...
}
Comment copied to answer.
If I've understood you correctly and your problem is that intellisense isn't working on the line
appContainer.ComponentRegistry.Registrations.Where(x => true);
You should probably try and disable your addons and see if that takes care of it as it's working fine for me. Since you say you had someone else confirm it, maybe start with any addons that your installations have in common.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autofac;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// First, create your application-level defaults using a standard
// ContainerBuilder, just as you are used to.
var builder = new ContainerBuilder();
var appContainer = builder.Build();
var registrations = appContainer.ComponentRegistry.Registrations.Where(x => x.Target.Equals("test"));
}
}
}
Try assigning the linq expression to a variable and see if it works

Resources