Assigning Visible Property of the Button to a Static Method Result

Assigning Visible Property of the Button to a Static Method Result

Kind of an interesting issue.. But as the error message states, the string <%= WebApplication1.SiteHelper.IsUserInRole("Admin") %> cannot be converted to a boolean.

Unfortunately i cannot explain why the expression isn't evaluated, but instead is treated like a string.

The reason why your <%# %> expression works as expected, is because it is treated much differently. When the Page is compiled into a class, then the compiler creates an event handler similar to this:

public void __DataBindingButton2(object sender, EventArgs e)
{
Button button = (Button) sender;
Page bindingContainer = (Page) button.BindingContainer;
button.Visible = HttpContext.Current.User.IsInRole("admin");
}

and hooks this method up to the Control.Databinding event on your control. As you can see, the <%# %> is this time properly treated as server code, and not just a random string.

So i guess the solution is either to use databinding, or go to the codebehind as AndreasKnudsen suggests.

Binding visibility to static property

CodeNaked's solution works, but it uses a Singleton which has downsides when doing unit-testing. I prefer to approach global access problems by just having one settings instance at the application root, i.e. the App-class.

e.g.

public partial class App : Application
{
private static Settings _settings = new Settings();
public static Settings Settings
{
get { return _settings; }
}

...

Where this property contains all the settings for the application. Binding then looks like this:

"{Binding Source={x:Static local:App.Settings}, Path=LabelsShown}"

Edit: If you are worried about dependencies you could also inject a reference to those settings in the constructor of any class where you need it, using its minimal interface.

e.g.

public class MyControl : ContentControl
{
public interface IMyControlSettings
{
public bool LabelsShown { get; set; }
}

private IMyControlSettings _settings;

public MyControl(IMyControlSettings settings)
{
_settings = settings;
DataContext = _settings; // For easy binding, in most cases you probably do not want to do that since it prevents DataContext inheritance.
}
}
public class Settings : Test.MyControl.IMyControlSettings, INotifyPropertyChanged
{
public bool LabelsShown { get; set; }
...
}

Why will %= % expressions as property values on a server-controls lead to a compile errors?

This:

<asp:Button runat="server" id="Button1" visible='<%= true %>' />

Does not evaluate to this:

<asp:Button runat="server" id="Button1" visible='true' />

<%= %> outputs directly to the response stream, and the asp markup is not part of the response stream. Its a mistake to assume the <%= %> operators are performing any kind of preprocessing on the asp markup.


As an aside, it helps to think about the ASP.NET lifecycle with respect to the <%# %> and <%= %> operators.

  • <%# %> has semantics more in common with assigning a value to an object. In the ASP.NET lifecycle, the <%# %> operators are evaluated before the page writes the first byte to the response buffer.

  • <%= %> means the same thing as Response.Write. We need to perform all of our databinding and form processing first, and output HTML to the response buffer at the very end of the ASP.NET lifecycle.

Binding a Button's visibility to a bool value in ViewModel

Assuming AdvancedFormat is a bool, you need to declare and use a BooleanToVisibilityConverter:

<!-- In your resources section of the XAML -->
<BooleanToVisibilityConverter x:Key="BoolToVis" />

<!-- In your Button declaration -->
<Button
Height="50" Width="50"
Style="{StaticResource MyButtonStyle}"
Command="{Binding SmallDisp}" CommandParameter="{Binding}"
Cursor="Hand" Visibility="{Binding Path=AdvancedFormat, Converter={StaticResource BoolToVis}}"/>

Note the added Converter={StaticResource BoolToVis}.

This is a very common pattern when working with MVVM. In theory you could do the conversion yourself on the ViewModel property (i.e. just make the property itself of type Visibility) though I would prefer not to do that, since now you are messing with the separation of concerns. An item's visbility should really be up to the View.

How to hide link button based on a result returned by a class ?

The reason is that this is for databinding expressions only: <%# Since the DetailsView is databound it works there.

If you would DataBind the page it worked also for the LinkButton outside of the DetailsView:

protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}

inline asp.net tags... sorting them all out (<%$, <%=, <%, <%#, etc.)

Side-note: be careful with static in ASP.NET. The static method does not yet hurt. But if you'd also use static fields you'd enter a minefield since it would be shared across all requests. Your current code-behind "work-around" is the better approach anyway.

Cleanest way to bind a Button's visibility to the contents of two textboxes

Edit: For silverlight this is probably the cleanest it gets:

<TextBox Text="{Binding TB1Text, Mode=TwoWay}" />
<TextBox Text="{Binding TB2Text, Mode=TwoWay}"/>
<Button Content="Lorem Ipsum" IsEnabled="{Binding ButtonIsEnabled}"/>
private string _TB1Text;
public string TB1Text
{
get { return _TB1Text; }
set
{
if (_TB1Text != value)
{
_TB1Text = value;
PropertyChanged.Notify(() => this.TB1Text);
PropertyChanged.Notify(() => this.ButtonIsEnabled);
}
}
}

private string _TB2Text;
public string TB2Text
{
get { return _TB2Text; }
set
{
if (_TB2Text != value)
{
_TB2Text = value;
PropertyChanged.Notify(() => this.TB2Text);
PropertyChanged.Notify(() => this.ButtonIsEnabled);
}
}
}

public bool ButtonIsEnabled
{
get { return !(String.IsNullOrEmpty(TB1Text) && String.IsNullOrEmpty(TB2Text)); }
}

(PropertyChanged.Notify is just an extension method which raises the event without the need to pass around strings)


Would not use a binding but a MultiDataTrigger:

<TextBox Name="tb1"/>
<TextBox Name="tb2"/>
<Button Content="Lorem Ipsum">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Text, ElementName=tb1}" Value="{x:Static sys:String.Empty}"/>
<Condition Binding="{Binding Text, ElementName=tb2}" Value="{x:Static sys:String.Empty}"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

By the way, you do not need a converter for your one TextBox case:

<Button Content="Lorem Ipsum" IsEnabled="{Binding Text.Length,
ElementName=MyTextBox}"/>

WinForms - PerfromClick() doesn't work when the button is not visible

I'll answer the following questions:

  1. Why PerfromClick doesn't work for an invisible button?
  2. What's a workaround for this issue?

Answer to 1 - If you look at the source code of the PerfromClick method, you see the first statement is a check: if (CanSelect) and if follow the code further, you see the CanSelect method returns false when the control is not enabled or is not visible. So that's the reason.

Answer to 2 - As a workaround, you can use the button's accessible object and invoke the default action which basically performs a click for a button:

button1.AccessibilityObject.DoDefaultAction();

Or as another workaround, use reflection to invoke the OnClick method:

button1.GetType().GetMethod("OnClick", 
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance)
.Invoke(button, new object[] { EventArgs.Empty });

Static variables in JavaScript

If you come from a class-based, statically typed object-oriented language (like Java, C++ or C#) I assume that you are trying to create a variable or method associated to a "type" but not to an instance.

An example using a "classical" approach, with constructor functions maybe could help you to catch the concepts of basic OO JavaScript:

function MyClass () { // constructor function
var privateVariable = "foo"; // Private variable

this.publicVariable = "bar"; // Public variable

this.privilegedMethod = function () { // Public Method
alert(privateVariable);
};
}

// Instance method will be available to all instances but only load once in memory
MyClass.prototype.publicMethod = function () {
alert(this.publicVariable);
};

// Static variable shared by all instances
MyClass.staticProperty = "baz";

var myInstance = new MyClass();

staticProperty is defined in the MyClass object (which is a function) and has nothing to do with its created instances, JavaScript treats functions as first-class objects, so being an object, you can assign properties to a function.

UPDATE: ES6 introduced the ability to declare classes through the class keyword. It is syntax sugar over the existing prototype-based inheritance.

The static keyword allows you to easily define static properties or methods in a class.

Let's see the above example implemented with ES6 classes:

class MyClass {  // class constructor, equivalent to  // the function body of a constructor  constructor() {    const privateVariable = 'private value'; // Private variable at the constructor scope    this.publicVariable = 'public value'; // Public property
this.privilegedMethod = function() { // Public Method with access to the constructor scope variables console.log(privateVariable); }; }
// Prototype methods: publicMethod() { console.log(this.publicVariable); }
// Static properties shared by all instances static staticProperty = 'static value';
static staticMethod() { console.log(this.staticProperty); }}
// We can add properties to the class prototypeMyClass.prototype.additionalMethod = function() { console.log(this.publicVariable);};
var myInstance = new MyClass();myInstance.publicMethod(); // "public value"myInstance.additionalMethod(); // "public value"myInstance.privilegedMethod(); // "private value"MyClass.staticMethod(); // "static value"

WPF: how to implement a button that make 2 other buttons visible with fading

After a lot of discussion, here is the result to solve this problem:

xaml:

<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication3"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Orientation="Horizontal">
<Button Name="btnSinglePlay" Visibility="Collapsed" my:VisibilityAnimation.IsActive="True">SinglePlay</Button>
<Button Name="btnPlay" Click="btnPlay_Click">Play</Button>
<Button Name="btnParallelPlay" Visibility="Collapsed" my:VisibilityAnimation.IsActive="True">ParallelPlay</Button>
</StackPanel>
</Grid>

C# to set the 2 sides button visible.

private void btnPlay_Click(object sender, RoutedEventArgs e)
{
btnSinglePlay.Visibility = Visibility.Visible;
btnParallelPlay.Visibility = Visibility.Visible;
}

And the c# code to permit the fade in/fade out. It comes from WPF Fade Animation so props to Anvaka, not to me.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Animation;

namespace WpfApplication3
{
public class VisibilityAnimation : DependencyObject
{
private const int DURATION_MS = 200;

private static readonly Hashtable _hookedElements = new Hashtable();

public static readonly DependencyProperty IsActiveProperty =
DependencyProperty.RegisterAttached("IsActive",
typeof(bool),
typeof(VisibilityAnimation),
new FrameworkPropertyMetadata(false, new PropertyChangedCallback(OnIsActivePropertyChanged)));

public static bool GetIsActive(UIElement element)
{
if (element == null)
{
throw new ArgumentNullException("element");
}

return (bool)element.GetValue(IsActiveProperty);
}

public static void SetIsActive(UIElement element, bool value)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
element.SetValue(IsActiveProperty, value);
}

static VisibilityAnimation()
{
UIElement.VisibilityProperty.AddOwner(typeof(FrameworkElement),
new FrameworkPropertyMetadata(Visibility.Visible, new PropertyChangedCallback(VisibilityChanged), CoerceVisibility));
}

private static void VisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// So what? Ignore.
}

private static void OnIsActivePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var fe = d as FrameworkElement;
if (fe == null)
{
return;
}
if (GetIsActive(fe))
{
HookVisibilityChanges(fe);
}
else
{
UnHookVisibilityChanges(fe);
}
}

private static void UnHookVisibilityChanges(FrameworkElement fe)
{
if (_hookedElements.Contains(fe))
{
_hookedElements.Remove(fe);
}
}

private static void HookVisibilityChanges(FrameworkElement fe)
{
_hookedElements.Add(fe, false);
}

private static object CoerceVisibility(DependencyObject d, object baseValue)
{
var fe = d as FrameworkElement;
if (fe == null)
{
return baseValue;
}

if (CheckAndUpdateAnimationStartedFlag(fe))
{
return baseValue;
}
// If we get here, it means we have to start fade in or fade out
// animation. In any case return value of this method will be
// Visibility.Visible.

var visibility = (Visibility)baseValue;

var da = new DoubleAnimation
{
Duration = new Duration(TimeSpan.FromMilliseconds(DURATION_MS))
};

da.Completed += (o, e) =>
{
// This will trigger value coercion again
// but CheckAndUpdateAnimationStartedFlag() function will reture true
// this time, and animation will not be triggered.
fe.Visibility = visibility;
// NB: Small problem here. This may and probably will brake
// binding to visibility property.
};

if (visibility == Visibility.Collapsed || visibility == Visibility.Hidden)
{
da.From = 1.0;
da.To = 0.0;
}
else
{
da.From = 0.0;
da.To = 1.0;
}

fe.BeginAnimation(UIElement.OpacityProperty, da);
return Visibility.Visible;
}

private static bool CheckAndUpdateAnimationStartedFlag(FrameworkElement fe)
{
var hookedElement = _hookedElements.Contains(fe);
if (!hookedElement)
{
return true; // don't need to animate unhooked elements.
}

var animationStarted = (bool)_hookedElements[fe];
_hookedElements[fe] = !animationStarted;

return animationStarted;
}
}
}


Related Topics



Leave a reply



Submit