I am trying to build a stylle sheet dynamically (based on certain business rules) Long story short it mostly works, except there is one css tag I cannot set min-height. I can hit height, but not min-height. both being valid css values
i.e
string h = "105mm";
Style dynamicClassStyle = new Style();
dynamicClassStyle.Height = new Unit(h);
Page.Header.StyleSheet.CreateStyleRule(dynamicClassStyle, null, ".make-display");
That renders a height tag alright, but what i really need is a min-height. i would love to be able to go
dynamicClassStyle.Min-Height = new Unit(h);
in order to get this
.make-display {
min-height:90mm;
}
You'll need to
inherit from Style,
add a MinHeight property and
override FillStyleAttributes to handle your new property.
You can then use an instance of this new (min-height aware) MinHeightStyle (instead of Style) in your own code.
The new class:
using System.Web.UI;
using System.Web.UI.WebControls;
public class MinHeightStyle : Style
{
public Unit MinHeight
{
get
{
var minHeight = this.ViewState["MinHeight"];
if (minHeight != null)
{
return (Unit)minHeight;
}
return Unit.Empty;
}
set
{
this.ViewState["MinHeight"] = value;
}
}
protected override void FillStyleAttributes(CssStyleCollection attributes, IUrlResolutionService urlResolver)
{
base.FillStyleAttributes(attributes, urlResolver);
if (!this.MinHeight.IsEmpty)
{
attributes.Add("min-height", this.MinHeight.ToString());
}
}
}
And your new code:
string h = "105mm";
MinHeightStyle dynamicClassStyle = new MinHeightStyle();
dynamicClassStyle.Height = new Unit(h);
dynamicClassStyle.MinHeight = new Unit(h);
Page.Header.StyleSheet.CreateStyleRule(dynamicClassStyle, null, ".make-display");
Which renders the following:
.make-display { min-height:105mm;height:105mm; }
The Style class does not conatin a property named as Min-Height. Checkout the MSDN link, so you can't add one.
Related
I am trying to write a code analysis extension for visual studio using MEF. I have implemented the ITagger interface for an IErrorTag along with the required ITaggerProvider. As a result, i get the expected squiggles in the editor window for the issues my code analysis finds. However, when hovering above the squiggles with the mouse, the respective tooltip content is never displayed.
Here is a minimalistic example which has the same problem:
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
using System;
using System.Collections.Generic;
namespace CodeAnalyzer
{
struct DummyIssue
{
public int Line; // one based line
public string ToolTip;
public DummyIssue(int line, string toolTip)
{
Line = line;
ToolTip = toolTip;
}
}
internal class DummyCodeCheckTagger : ITagger<IErrorTag>
{
readonly List<DummyIssue> mIssues;
readonly ITextView TextView;
public DummyCodeCheckTagger(ITextView textView)
{
TextView = textView;
mIssues = new List<DummyIssue>
{
new DummyIssue(1, "asldfjoqwet"),
new DummyIssue(7, "ASASDAER")
};
textView.LayoutChanged += Update;
}
public event EventHandler<SnapshotSpanEventArgs> TagsChanged;
private void Update(object sender, TextViewLayoutChangedEventArgs args)
{
TagsChanged?.Invoke(this, new SnapshotSpanEventArgs(new SnapshotSpan(args.NewSnapshot, 0, args.NewSnapshot.Length)));
}
IEnumerable<ITagSpan<IErrorTag>> ITagger<IErrorTag>.GetTags(NormalizedSnapshotSpanCollection spans)
{
var issues = mIssues;
foreach (var span in spans)
{
foreach (var issue in issues)
{
int zeroBasedLine = issue.Line - 1;
ITextSnapshotLine snapshotLine = TextView.TextSnapshot.GetLineFromLineNumber(zeroBasedLine);
SnapshotSpan snapshotSpan = snapshotLine.Extent;
if (spans.IntersectsWith(snapshotSpan))
{
yield return new TagSpan<IErrorTag>(snapshotSpan, new ErrorTag(PredefinedErrorTypeNames.SyntaxError, issue.ToolTip));
}
}
}
}
}
}
The result looks like this:
tooltip not displaying
What am i missing to get the tooltip displayed?
Fater's comment above led me to think about the problem again. Since i already tried the suggestions in the document posted by fater without success, i started thinking if the problem could be somewhere else.
It turns out that the ITagger implementation was not the problem, but the ITaggerProvider implementation caused the strange behavior. For that,
I pretty much followed the VSIX ErrorList example implementing a SpellChecker, which contains the following code
/// <summary>
/// Create a tagger that does spell checking on the view/buffer combination.
/// </summary>
public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
{
ITagger<T> tagger = null;
// Only attempt to spell check on the view's edit buffer (and multiple views could have that buffer open simultaneously so
// only create one instance of the spell checker.
if ((buffer == textView.TextBuffer) && (typeof(T) == typeof(IErrorTag)))
{
var spellChecker = buffer.Properties.GetOrCreateSingletonProperty(typeof(SpellChecker), () => new SpellChecker(this, textView, buffer));
// This is a thin wrapper around the SpellChecker that can be disposed of without shutting down the SpellChecker
// (unless it was the last tagger on the spell checker).
tagger = new SpellCheckerTagger(spellChecker) as ITagger<T>;
}
return tagger;
}
The point is, that the code above only creates an ITagger for a certain view. In that case the created tagger is used only for providing the squiggles in the editor window view. Visual Studio uses a different tagger instance for providing the tooltips for the squiggles and another tagger instance for coloring the scroll bar in the editor window. I had assumed that this would be done by one single tagger instance.
I really want to implement a loading circle in the searchbar (overriding the cancel button while loading) on android like Netflix.
Currently Im getting the cancel button with
var searchBttId = searchView.Resources.GetIdentifier("android:id/search_close_btn", null, null);
var imbCancel = (searchView.FindViewById(searchBttId) as Android.Widget.ImageView)
but I dont know how to add a progresscircle and how to interact with it. I thought of adding it with AddView, but nothing pops up when testing.
Test:
var _v = new Android.Widget.ImageView(Context) { };
_v.SetBackgroundColor(new Android.Graphics.Color(200, 0, 0));
var c = new LayoutParams(500, 500);
_v.LayoutParameters = c;
searchView.AddView(_v);
I really want to implement a loading circle in the searchbar (overriding the cancel button while loading) on android like Netflix.
According to your description, you want to override searchbar's search_close_btn using other icon, like loading circle? Am I right?
If yes, I suggest you can use custom render to change searchbar's search_close_btn image.
Firstly, create custom Searchbar that inherit SearchBar in Form.cs.
public class MySearchBar:SearchBar
{
}
Then implementing custom render in Android platform.
[assembly: ExportRenderer(typeof(MySearchBar), typeof(MySearchBarRenderer))]
namespace demo3.Droid
{
public class MySearchBarRenderer: SearchBarRenderer
{
public MySearchBarRenderer(Context context):base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (Control != null)
{
var searchView = Control;
int searchViewCloseButtonId = Control.Resources.GetIdentifier("android:id/search_close_btn", null, null);
var closeIcon = searchView.FindViewById(searchViewCloseButtonId);
(closeIcon as ImageView).SetImageResource(Resource.Drawable.plu3);
}
}
}
}
Please see the gif:
About Custom Render, you can take a look:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/entry
My Form has a DataGridView control and Column 0 is of type DataGridViewImageColumn.
When the Form is first displayed, an empty DataGridView control is displayed and Column 0 has a rectangle with a red X in it.
The same icon is displayed when I add a row to the control.
How do I get rid of the box with red X and display nothing?
I have tried the following. Globals.ERROR_LIST_SEVERITY has a value of 0.
dataGridView_ErrorList.Columns[Globals.ERROR_LIST_SEVERITY].DefaultCellStyle.NullValue = null;
Also tried brute force just to see if it would work:
dataGridView_ErrorList.Rows[0].Cells[0].Value = null;
Any idea why this doesn't work? Do I need to create a blank image and assign the value to the blank image?
That seems silly when setting the null value should work.
As described in the MSDN Docs, in the Remarks section of the DataGridViewImageColumn Class, to replace the default Error Image with a custom Image, requires a custom class derived from DataGridViewImageCell.
This allows to override the DefaultNewRowValue property, usually read-only, setting the custom Image.
Also, eventually, to override the PaintErrorIcon method.
This is an implementation of custom DataGridViewImageColumn, coupled with a custom DataGridViewImageCell, which can be configured to show a different default Image when no Image is specified or the bound field value is null.
If no image is specified, the cell will show an empty content, also in the DataGridView New Row.
The class constructor has several overloads. You can specify:
The Column Name (defaults to ImageColumn).
The Column's Header text (defaults to ImageColumn).
The DataPropertyName, if the Column will be bound to a DataSource field (defaults to string.Empty).
The Image used as placeholder when no image is present (defaults to an empty Bitmap)
To add the custom Image column to a DataGridView, use the DataGridView.Columns.Add() method, passing a new DGVCustomImageColumn, initialized as needed.
Here, I'm just setting the Column.Name, the HeaderText and the DataPropertyName:
dataGridView1.Columns.Add(new DGVCustomImageColumn("ImageCol", "Image", "ImageField"));
The DGVCustomImageColumn class:
using System.Drawing;
using System.Windows.Forms;
class DGVCustomImageColumn : DataGridViewImageColumn
{
private Bitmap dgvErrorBitmap = new Bitmap(1, 1);
public DGVCustomImageColumn()
: this("ImageColumn", "ImageColumn", string.Empty, null) { }
public DGVCustomImageColumn(string colName, string headerText)
: this(colName, headerText, string.Empty, null) { }
public DGVCustomImageColumn(string colName, string headerText, string dataField)
: this(colName, headerText, dataField, null) { }
public DGVCustomImageColumn(string colName, string headerText, string dataField, Bitmap errorImage)
{
this.CellTemplate = new CustImageCell(errorImage ?? dgvErrorBitmap);
this.DataPropertyName = dataField;
this.HeaderText = headerText;
this.Image = errorImage ?? dgvErrorBitmap;
this.Name = colName;
}
protected class CustImageCell : DataGridViewImageCell
{
public CustImageCell() : this(null) { }
public CustImageCell(Bitmap defaultImage) => this.DefaultNewRowValue = defaultImage;
public override object DefaultNewRowValue { get; }
}
}
I have encountered this problem, but I overcome it with the following statement
dataGridView1.Columns[0].DefaultCellStyle.NullValue = null;
dataGridView1.Rows[0].Cells[0].Value = null;
So the problem is that I created a custom Control which holds 3 other controls deriving from FrameworkElement:
class TextArea : Control {
private List<LocalViewBase> views;
private Views.TextView.View textView;
private Views.CaretView.View caretView;
private Views.SelectionView.View selectionView;
protected override int VisualChildrenCount => views.Count;
protected override Visual GetVisualChild(int index) => views[index];
public TextArea() {
views = new List<LocalViewBase>();
SetViews();
}
private void SetViews() {
textView = new Views.TextView.View() { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };
textInfo = new LocalTextInfo(textView);
selectionView = new Views.SelectionView.View(textInfo) { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };
caretView = new Views.CaretView.View(textInfo) { Margin = new Thickness(EditorConfiguration.GetTextAreaLeftMargin(), 0, 0, 0) };
foreach (var view in new LocalViewBase[] { selectionView, textView, caretView }) {
views.Add(view);
AddVisualChild(view);
AddLogicalChild(view);
}
}
}
public abstract class LocalViewBase : FrameworkElement { }
LocalViewBase is currently an empty class deriving from FrameworkElement.
The problem I'm dealing with right now is that only the OnRender of the earliest added child is being called - in this case selectionView - and only it is drawn with a proper margin. I tried #devhedgehog's answer from here: WPF - Visual tree not used for drawing? but it doesn't do the trick for me. Even if I extend the Panel class instead of Control and use its Children collection instead of calls to AddVisualChild() and AddLogicalChild(), still the views aren't draw with a proper margin. I also tried every method like InvalidateWhatever() but it also didn't help.
Probably the other views are not drawn with a correct margin, because all of them are stacked on top of each other and WPF "thinks" that only the selectionView is visible, so the actual question is - how do I convince it to think otherwise? :)
The solution for this problem was really simple. I had to extend StackPanel class and override the ArrangeOverride method (for each child to be put on x, y = 0, 0).
public abstract class StackablePanel : StackPanel {
protected override Size ArrangeOverride(Size arrangeSize) {
foreach (var child in Children) {
var uiElement = (UIElement)child;
var rcChild = new Rect(0, 0, Width, Height);
uiElement.Arrange(rcChild);
}
return arrangeSize;
}
}
In one of my previous approaches to this problem I extended the Panel class, but it was not enough - the default implementation for ArrangeOverride doesn't put child UIElement's as I would desire and it wasn't passing a correct Size instance to the child's Arrange method.
Now when my TextArea class extends this one, each of its child views is drawn correctly and its OnRender method is called.
I am trying to create some custom treeviews. Everything is working fine so far, but I got a little problem with styles. I have a simple "RedBackground" Style which I add to the resources of the Window. When adding normal elements, it works fine.
When using a custom item template to render treeview items, my resource is ignored. If I add the resource directly to the template it works fine (as marked in code)...
I obviously do not want to have to add styles to the ItemTemplate direclty, would be very complicated in further development. I think I am missing some kind of "Binding" or "Lookup"... I think it is related to dependency properties... Or something in this direction.
Perhaps anyone has more insights, here is the code creating the template (inside util class, but thats just to keep all clean):
var hdt = new HierarchicalDataTemplate(t)
{
ItemsSource = new Binding("Children")
};
var tb = new FrameworkElementFactory(typeof (TextBlock));
tb.SetBinding(TextBlock.TextProperty, new Binding("Header"));
hdt.VisualTree = tb;
// This way it works...
TextBlockStyles.AddRedBackground(hdt.Resources);
return hdt;
And here my very simple custom tree view
public class TreeViewCustom<T> : TreeView
{
public TreeViewCustom()
{
MinWidth = 300;
MinHeight = 600;
ItemTemplate = TreeViewTemplates.TryGetTemplate(typeof(T));
// This is ignored.... (Also when set as resource to window)
TextBlockStyles.AddRedBackground(Resources);
}
}
Ok, and to be sure, here the code which creates the Style:
public static class TextBlockStyles
{
public static void AddRedBackground(ResourceDictionary r)
{
var s = CreateRedBackground();
r.Add(s.TargetType, s);
}
private static Style CreateRedBackground()
{
var s = new Style(typeof(TextBlock));
s.Setters.Add(new Setter
{
Property = TextBlock.BackgroundProperty,
Value = new SolidColorBrush(Colors.Red)
});
return s;
}
}
Thanks for any tips...
Chris
Is this a problem with "inheritance"? Not all properties are inherited, read more here:
Property Value Inheritance: http://msdn.microsoft.com/en-us/library/ms753197.aspx