Background image throws exception when used in custom editor - c#

I am using custom editor collection for a property(which contains the collection of custom controls) in custom control. I have used the UITypeEditor for this property as given in this link . Now when clicking the property, UI editors shows but when clicking the background image it shows the following error.
Background image throws exception when used in custom editor
Can anyone please help me to resolve this?
Here is my property
/// <summary>
/// Gets or sets the value to the items of the the TreeNavigator.
/// </summary>
[Browsable(true), DefaultValue(null),
Category("Appearance"), Description("Gets or sets the value to the items of the Custom control.")]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[TypeConverter(typeof(ItemConverter))]
[Editor(typeof(ItemCustomCollectionEditor), typeof(UITypeEditor))]
public MenuItemCollection Items
{
get
{
if (items == null)
{
items = new MenuItemCollection((this.Parent.Parent as CustomControl));
}
return items;
}
set
{
if (items != value)
{
items = value;
PerformLayout();
}
}
}
and this my custom editor
public class ItemCustomCollectionEditor : System.Drawing.Design.UITypeEditor
{
/// <summary>
/// delegate for collection changed event
/// </summary>
public delegate void CollectionChangedEventHandler(object sender, object instance, object value);
/// <summary>
/// Fires when the Collection in the item changes
/// </summary>
public event CollectionChangedEventHandler CollectionChanged;
/// <summary>
/// ITypeDescriptorContext
/// </summary>
private ITypeDescriptorContext _context;
/// <summary>
/// IWindowsFormsEditorService
/// </summary>
private IWindowsFormsEditorService edSvc = null;
/// <summary>
/// ItemCustomCollectionEditor constructor
/// </summary>
public ItemCustomCollectionEditor()
{ }
/// <summary>
/// EditVaue method is used to edit the value in the Item Collection
/// </summary>
/// <param name="context">Provides information about container</param>
/// <param name="provider">Object providing custom support</param>
/// <param name="value">Object of the container</param>
/// <returns>Returns the object of the container</returns>
public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
{
Menuitemcollection coll = value as Menuitemcollection;
CustomControl owner = coll.container;
if (context != null && context.Instance != null && provider != null)
{
object originalValue = value;
_context = context;
if (provider != null)
{
edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
}
if (edSvc != null)
{
ItemCollectionEditorForm collEditorFrm = CreateForm(owner);
collEditorFrm.ItemAdded += new ItemCollectionEditorForm.InstanceEventHandler(ItemAdded);
collEditorFrm.ItemRemoved += new ItemCollectionEditorForm.InstanceEventHandler(ItemRemoved);
collEditorFrm.Collection = (IList)value;
context.OnComponentChanging();
if (edSvc.ShowDialog(collEditorFrm) == DialogResult.OK)
{
OnCollectionChanged(context.Instance, value);
context.OnComponentChanged();
value = collEditorFrm.Collection;
}
}
}
return value;
}
/// <summary>
/// GetEditStyle for the editor
/// </summary>
/// <param name="context">Provides information about container</param>
/// <returns>Returns EditorStyle</returns>
public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
{
if (context != null && context.Instance != null)
{
return UITypeEditorEditStyle.Modal;
}
return UITypeEditorEditStyle.Modal;
}
/// <summary>
/// Indicates the ItemAdded
/// </summary>
/// <param name="sender">Sender as container</param>
/// <param name="item">Added Items in the container</param>
private void ItemAdded(object sender, object item)
{
if (_context != null && _context.Container != null)
{
IComponent icomp = item as IComponent;
if (icomp != null)
{
_context.Container.Add(icomp);
}
}
}
/// <summary>
/// Indicates the ItemAdded
/// </summary>
/// <param name="sender">Sender as container</param>
/// <param name="item">Added Items in the container</param>
private void ItemRemoved(object sender, object item)
{
if (_context != null && _context.Container != null)
{
IComponent icomp = item as IComponent;
if (icomp != null)
{
_context.Container.Remove(icomp);
}
}
}
/// <summary>
/// Triggers the CollectionChanged event
/// </summary>
/// <param name="instance">Object that carries the Item</param>
/// <param name="value">Value of the Item with all its associated properties</param>
protected virtual void OnCollectionChanged(object instance, object value)
{
if (CollectionChanged != null)
{
CollectionChanged(this, instance, value);
}
}
/// <summary>
/// Creates the form
/// </summary>
/// <param name="owner">CustomControl Form</param>
/// <returns>Returns the new CollectionEditorForm</returns>
protected virtual ItemCollectionEditorForm CreateForm(CustomControl owner)
{
return new ItemCollectionEditorForm(owner);
}
}

Related

Custom Checkbox Default Text Binding on Xamarin

I have a custom Checkbox is implemented as below;
public class CheckBox : View, INotifyPropertyChanged
{
/// <summary>
/// The checked state property.
/// </summary>
public static readonly BindableProperty CheckedProperty =
BindableProperty.Create<CheckBox, bool>(
p => p.Checked, false, BindingMode.TwoWay, propertyChanged: OnCheckedPropertyChanged);
/// <summary>
/// The checked text property.
/// </summary>
public static readonly BindableProperty CheckedTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.CheckedText, string.Empty, BindingMode.TwoWay);
/// <summary>
/// The unchecked text property.
/// </summary>
public static readonly BindableProperty UncheckedTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.UncheckedText, string.Empty);
/// <summary>
/// The default text property.
/// </summary>
public static readonly BindableProperty DefaultTextProperty =
BindableProperty.Create<CheckBox, string>(
p => p.Text, string.Empty,BindingMode.TwoWay, propertyChanged: OnDefaultTextChanged);
/// <summary>
/// Identifies the TextColor bindable property.
/// </summary>
///
/// <remarks/>
public static readonly BindableProperty TextColorProperty =
BindableProperty.Create<CheckBox, Color>(
p => p.TextColor, Color.Default);
/// <summary>
/// The font size property
/// </summary>
public static readonly BindableProperty FontSizeProperty =
BindableProperty.Create<CheckBox, double>(
p => p.FontSize, -1);
/// <summary>
/// The font name property.
/// </summary>
public static readonly BindableProperty FontNameProperty =
BindableProperty.Create<CheckBox, string>(
p => p.FontName, string.Empty);
/// <summary>
/// The checked changed event.
/// </summary>
public event EventHandler<EventArgs<bool>> CheckedChanged;
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
public bool Checked
{
get
{
return this.GetValue<bool>(CheckedProperty);
}
set
{
if (this.Checked != value)
{
this.SetValue(CheckedProperty, value);
this.CheckedChanged.Invoke(this, value);
}
}
}
/// <summary>
/// Gets or sets a value indicating the checked text.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string CheckedText
{
get
{
return this.GetValue<string>(CheckedTextProperty);
}
set
{
this.SetValue(CheckedTextProperty, value);
}
}
/// <summary>
/// Gets or sets a value indicating whether the control is checked.
/// </summary>
/// <value>The checked state.</value>
/// <remarks>
/// Overwrites the default text property if set when checkbox is checked.
/// </remarks>
public string UncheckedText
{
get
{
return this.GetValue<string>(UncheckedTextProperty);
}
set
{
this.SetValue(UncheckedTextProperty, value);
}
}
/// <summary>
/// Gets or sets the text.
/// </summary>
public string DefaultText
{
get
{
return this.GetValue<string>(DefaultTextProperty);
}
set
{
this.SetValue(DefaultTextProperty, value);
NotifyPropertyChanged("DefaultTextProperty");
NotifyPropertyChanged("DefaultText");
}
}
/// <summary>
/// Gets or sets the color of the text.
/// </summary>
/// <value>The color of the text.</value>
public Color TextColor
{
get
{
return this.GetValue<Color>(TextColorProperty);
}
set
{
this.SetValue(TextColorProperty, value);
}
}
/// <summary>
/// Gets or sets the size of the font.
/// </summary>
/// <value>The size of the font.</value>
public double FontSize
{
get
{
return (double)GetValue(FontSizeProperty);
}
set
{
SetValue(FontSizeProperty, value);
}
}
/// <summary>
/// Gets or sets the name of the font.
/// </summary>
/// <value>The name of the font.</value>
public string FontName
{
get
{
return (string)GetValue(FontNameProperty);
}
set
{
SetValue(FontNameProperty, value);
}
}
/// <summary>
/// Gets the text.
/// </summary>
/// <value>The text.</value>
public string Text
{
get
{
return this.Checked
? (string.IsNullOrEmpty(this.CheckedText) ? this.DefaultText : this.CheckedText)
: (string.IsNullOrEmpty(this.UncheckedText) ? this.DefaultText : this.UncheckedText);
}
}
/// <summary>
/// Called when [checked property changed].
/// </summary>
/// <param name="bindable">The bindable.</param>
/// <param name="oldvalue">if set to <c>true</c> [oldvalue].</param>
/// <param name="newvalue">if set to <c>true</c> [newvalue].</param>
private static void OnCheckedPropertyChanged(BindableObject bindable, bool oldvalue, bool newvalue)
{
var checkBox = (CheckBox)bindable;
checkBox.Checked = newvalue;
}
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I have default text bindable property, that I want to set the value from coming web service via Binding.
The code I tried on Xaml is as below;
<uikit:CheckBox x:Name="CheckBox" WidthRequest="250" HeightRequest="100" FontSize="13" DefaultText="{Binding FirstText,Mode=TwoWay}" CheckedChanged="CheckBox_Clicked" TextColor="#263238" />
I am not able to do so... I tried setting Binding Context in both Xaml and Codebehind.
What am I doing wrong?
Could you please help me?
I have also added PropertyChanged Event Handler, my updated code is as above. It still does not update.
BR,
add this at end
public void RaiseCheckedChanged (bool val)
{
if (CheckedChanged != null)
CheckedChanged (this, new EventArgs<bool> (val));
}
and add this class in same file
public class EventArgs<T> : EventArgs
{
/// <summary>
/// Initializes a new instance of the <see cref="EventArgs"/> class.
/// </summary>
/// <param name="value">Value of the argument</param>
public EventArgs(T value)
{
this.Value = value;
}
/// <summary>
/// Gets the value of the event argument
/// </summary>
public T Value { get; private set; }
}
public static class BindableObjectExtensions
{
/// <summary>
/// Gets the value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="bindableObject">The bindable object.</param>
/// <param name="property">The property.</param>
/// <returns>T.</returns>
public static T GetValue<T>(this BindableObject bindableObject, BindableProperty property)
{
return (T)bindableObject.GetValue(property);
}
}
public static class EventExtensions
{
/// <summary>
/// Raise the specified event.
/// </summary>
/// <param name="handler">Event handler.</param>
/// <param name="sender">Sender object.</param>
/// <param name="value">Argument value.</param>
/// <typeparam name="T">The value type.</typeparam>
public static void Invoke<T>(this EventHandler<EventArgs<T>> handler, object sender, T value)
{
var handle = handler;
if (handle != null)
{
handle(sender, new EventArgs<T>(value));
}
}
/// <summary>
/// Tries the invoke.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="handler">The handler.</param>
/// <param name="sender">The sender.</param>
/// <param name="args">The arguments.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
public static bool TryInvoke<T>(this EventHandler<T> handler, object sender, T args) where T : EventArgs
{
var handle = handler;
if (handle == null) return false;
handle(sender, args);
return true;
}
}

How to move through all controls inside controls in Asp.Net WebForm?

How to move through all controls inside Panel Web Control or any other control?
control.FindControls("name") finds only controls in the same level only
below is an answer with high speed and lower resources with multitasking
/// <summary>
/// Start from Control and move through all inside controls to check if can execute and
/// execute ctrlAction if canExecute results true
/// </summary>
/// <typeparam name="T">
/// Any Control or object inherits System.Web.UI.Control
/// </typeparam>
/// <param name="ctrl">
/// the System.Web.UI.Control to traverse from and inside
/// </param>
/// <param name="ctrlAction">
/// the action to execute on the valid control
/// </param>
/// <param name="canExecute">
/// to check if the current reached control is valid for ctrlAction execution
/// </param>
public static void ExApply<T>(
this Control ctrl, Action<T> ctrlAction, Predicate<T> canExecute = null) where T : Control
{
// if ctrl is null return null
if (ctrl == null) { return; }
// to handle multitasking on the valid controls
LinkedList<Task> taskList = new LinkedList<Task>();
// start control traverse through all controls from and inside
ctrl._exApply(canExecute, ctrlAction, taskList);
// Waiting not finished, clean and clear resources
taskList._exWaitAndDispose();
}
/// <summary>
/// Start from ControlCollection and move through all inside controls to check if can execute and
/// execute ctrlAction if canExecute results true
/// </summary>
/// <typeparam name="T">
/// Any Control or object inherits System.Web.UI.Control
/// </typeparam>
/// <param name="ctrls">
/// the System.Web.UI.ControlCollection to traverse from and inside
/// </param>
/// <param name="ctrlAction">
/// the action to execute on the valid control
/// </param>
/// <param name="canExecute">
/// to check if the current reached control is valid for ctrlAction execution
/// </param>
public static void ExApply<T>(
this ControlCollection ctrls, Action<T> ctrlAction, Predicate<T> canExecute = null)
where T : Control
{
// if ctrls is null return null
if (ctrls == null) { return; }
// to handle multitasking on the valid controls
LinkedList<Task> taskList = new LinkedList<Task>();
// start control traverse through all controls from and inside
ctrls._exApply(canExecute, ctrlAction, taskList);
// Waiting not finished, clean and clear resources
taskList._exWaitAndDispose();
}
private static void _exApply<T>(
this Control ctrl, Predicate<T> canExecute, Action<T> ctrlAction, LinkedList<Task> taskList)
where T : Control
{
// if ctrl is null no more moves needed
if (ctrl == null) { return; }
// if ctrl can be casted and has no empty id
if ((ctrl is T castedCtrl) && castedCtrl.ID.ExIsNotNone())
{
// if canExecute is null or returned true result
if (canExecute == null || (canExecute != null && canExecute(castedCtrl)))
{
// add castedCtrl as an asynchronous task
taskList.AddLast(Task.Run(() => ctrlAction(castedCtrl)));
// check first node task if completed to remove and dispose
taskList._exDisposeFirsts();
}
}
// move more deep into inside controls
if (ctrl.Controls != null && ctrl.Controls.Count > 0)
{
ctrl.Controls._exApply(canExecute, ctrlAction, taskList);
}
}
private static void _exApply<T>(
this ControlCollection ctrls, Predicate<T> canExecute, Action<T> ctrlAction,
LinkedList<Task> taskList) where T : Control
{
for (int index = 0; index < ctrls.Count; index++)
{
// move through control to validate and apply ctrlAction
ctrls[index]?._exApply(canExecute, ctrlAction, taskList);
}
}
private static void _exDisposeFirsts(this LinkedList<Task> taskList)
{
while (taskList.Count > 0 && taskList.First.Value.IsCompleted)
{
taskList.First.Value.Dispose();
taskList.RemoveFirst();
}
}
private static void _exWaitAndDispose(this LinkedList<Task> taskList)
{
taskList._exDisposeFirsts();
if (taskList.Count < 1) { return; }
Task[] tasks = new Task[taskList.Count];
taskList.CopyTo(tasks, 0);
taskList.Clear();
Task.WaitAll(tasks);
tasks.ExDispose();
}
/// <summary>
/// Smaller Size name and usage from "string.IsNullOrWhiteSpace(text)" Indicates whether a
/// specified string is null, empty, or consists only of white-space characters.
/// </summary>
/// <param name="text">The string to test</param>
/// <returns>
/// true if the value parameter is null or System.String.Empty, or if value consists
/// exclusively of white-space characters.
/// </returns>
public static bool ExIsNone(this string text) => string.IsNullOrWhiteSpace(text);
/// <summary>
/// Smaller Size name and usage from "!string.IsNullOrWhiteSpace(text)" Indicates whether a
/// specified string is not null, not empty, or not consists only of white-space characters.
/// </summary>
/// <param name="text">The string to test</param>
/// <returns>
/// true if the value parameter is not null or not System.String.Empty, or if value not consists
/// exclusively of white-space characters.
/// </returns>
public static bool ExIsNotNone(this string text) => text.ExIsNone().ExIs(false);
/// <summary>
/// Use for easier code reading instead of inverse ! character and ambiguous names
/// </summary>
/// <param name="value">value to test</param>
/// <param name="compareValue">value to compare with</param>
/// <returns>true is equal otherwise false</returns>
public static bool ExIs(this bool value, bool compareValue) => value == compareValue;

WPF button property on user control not showing properties in property pane

I've been beating my head against the wall over this for days now and I can't seem to find any info that fits my problem.
So, I have this toolbar Usercontrol that's meant to be dropped in to an application. This toolbar has a property exposed called "FullExtentButton" which is a reference to the button. What I want is to expose the properties of this button in the designer properties pane on the toolbar user control so the developers can set the properties directly from the designer.
In WinForms, this was very easy to do. WPF, not so much (unless I'm just blind).
In my tool bar code:
[Category("Standard Buttons")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public MyToolbarButton FullExtentButton
{
get;
private set;
}
This value is set in the constructor the user control:
public MyToolbar()
{
InitializeComponent();
FullExtentButton = new MyToolbarButton("FullExtent", "/Utilities;component/Resources/full_extent_16x16.png");
}
The button itself is quite simple:
public class MyToolbarButton
: Freezable
{
#region Dependency Properties.
/// <summary>
/// Dependency property for the <see cref="IsVisible"/> property.
/// </summary>
public static DependencyProperty IsVisibleProperty = DependencyProperty.Register("IsVisible", typeof(bool), typeof(MyToolbarButton),
new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions
.BindsTwoWayByDefault, Visible_Changed));
/// <summary>
/// Dependency property for the <see cref="IsEnabled"/> property.
/// </summary>
public static DependencyProperty IsEnabledProperty = DependencyProperty.Register("IsEnabled", typeof(bool), typeof(MyToolbarButton),
new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Enabled_Changed));
/// <summary>
/// Dependency property for the <see cref="ToolTip"/> property.
/// </summary>
public static DependencyProperty ToolTipProperty = DependencyProperty.Register("ToolTip", typeof(string), typeof(MyToolbarButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, ToolTip_Changed));
/// <summary>
/// Dependency property for the <see cref="Glyph"/> property.
/// </summary>
public static DependencyProperty GlyphProperty = DependencyProperty.Register("Glyph", typeof(ImageSource), typeof(MyToolbarButton),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Glyph_Changed));
/// <summary>
/// Dependency property for the <see cref="ID"/> property.
/// </summary>
public static DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(string), typeof(MyToolbarButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
/// <summary>
/// Dependency property for the <see cref="ClickedCommand"/> property.
/// </summary>
public static DependencyProperty ClickedCommandProperty = DependencyProperty.Register("ClickedCommand", typeof(IMyRelayCommand<string>),
typeof(MyToolbarButton),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
#endregion
#region Variables.
// The default image source for the button glyph.
private readonly Uri _defaultImageSource;
#endregion
#region Properties.
/// <summary>
/// Property to set or return the command to execute when the button is clicked.
/// </summary>
public IMyRelayCommand<string> ClickedCommand
{
get
{
return (IMyRelayCommand<string>)GetValue(ClickedCommandProperty);
}
set
{
SetValue(ClickedCommandProperty, value);
}
}
/// <summary>
/// Property to set or return the ID of the button.
/// </summary>
public string ID
{
get
{
object value = GetValue(IDProperty);
return value == null ? string.Empty : value.ToString();
}
set
{
SetValue(IDProperty, value);
}
}
/// <summary>
/// Property to set or return the glyph for this button.
/// </summary>
public ImageSource Glyph
{
get
{
return GetValue(GlyphProperty) as ImageSource;
}
set
{
SetValue(GlyphProperty, value);
}
}
/// <summary>
/// Property to set or return the tool tip for the button.
/// </summary>
public string ToolTip
{
get
{
object value = GetValue(ToolTipProperty);
return value == null ? string.Empty : value.ToString();
}
set
{
SetValue(ToolTipProperty, value);
}
}
/// <summary>
/// Property to set or return whether the button is visible or not.
/// </summary>
public bool IsVisible
{
get
{
return (bool)GetValue(IsVisibleProperty);
}
set
{
SetValue(IsVisibleProperty, value);
}
}
/// <summary>
/// Property to set or return whether the button is enabled or not.
/// </summary>
public bool IsEnabled
{
get
{
return (bool)GetValue(IsEnabledProperty);
}
set
{
SetValue(IsEnabledProperty, value);
}
}
#endregion
#region Methods.
/// <summary>
/// Function to handle a change to the <see cref="GlyphProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Glyph_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// Function to handle a change to the <see cref="IsVisibleProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Visible_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// Function to handle a change to the <see cref="IsEnabledProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Enabled_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable" /> derived class.
/// </summary>
/// <returns>The new instance.</returns>
protected override Freezable CreateInstanceCore()
{
return new MyToolbarButton();
}
#endregion
#region Constructor/Finalizer.
/// <summary>
/// Initializes a new instance of the <see cref="MyToolbarButton"/> class.
/// </summary>
/// <param name="buttonID">The ID of the button being clicked.</param>
/// <param name="defaultImageSource">The default image source URI for the glyph used by the button.</param>
internal MyToolbarButton(string buttonID, string defaultImageSource)
{
ID = buttonID;
IsVisible = true;
IsEnabled = true;
ToolTip = string.Empty;
if (!string.IsNullOrWhiteSpace(defaultImageSource))
{
_defaultImageSource = new Uri(defaultImageSource, UriKind.Relative);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="MyToolbarButton"/> class.
/// </summary>
public MyToolbarButton()
{
// This is here to keep the XAML designer from complaining.
}
#endregion
But, when I view the button property on my user control in the XAML designer, and expand its properties I get this:
As you can see, there are no properties under that property in the XAML designer. What I want is to have the properties for that button appear under the "FullExtentsButton" property so that my developers can modify the properties, but not be able to create/remove the instance that's already there.
I've tried making the FullExtentButton property on my UserControl a DependencyProperty, but that didn't fix anything.
This is part of a standard toolbar that we want to use across applications, so enforcing consistency is pretty important for us. Plus it will allow our devs to focus on other parts of applications rather than reimplementing the same thing over and over (which is what we're having to do right now).
So, that said, I'm at my wits end here, what am I doing wrong?
Using this code which I had to change somewhat to get it to compile....
/// <summary>
/// Interaction logic for MyToolBarButton.xaml
/// </summary>
public partial class MyToolBarButton : UserControl
{
public MyToolBarButton()
{
InitializeComponent();
}
#region Dependency Properties.
/// <summary>
/// Dependency property for the <see cref="IsVisible"/> property.
/// </summary>
public static DependencyProperty IsVisibleProperty = DependencyProperty.Register("IsVisible", typeof(bool), typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions
.BindsTwoWayByDefault, Visible_Changed));
/// <summary>
/// Dependency property for the <see cref="IsEnabled"/> property.
/// </summary>
public static DependencyProperty IsEnabledProperty = DependencyProperty.Register("IsEnabled", typeof(bool), typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(true,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Enabled_Changed));
/// <summary>
/// Dependency property for the <see cref="ToolTip"/> property.
/// </summary>
public static DependencyProperty ToolTipProperty = DependencyProperty.Register("ToolTip", typeof(string), typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(ToolTipPropertyChanged)));
private static void ToolTipPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
throw new NotImplementedException();
}
/// <summary>
/// Dependency property for the <see cref="Glyph"/> property.
/// </summary>
public static DependencyProperty GlyphProperty = DependencyProperty.Register("Glyph", typeof(ImageSource), typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(null,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, Glyph_Changed));
/// <summary>
/// Dependency property for the <see cref="ID"/> property.
/// </summary>
public static DependencyProperty IDProperty = DependencyProperty.Register("ID", typeof(string), typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(string.Empty,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
/// <summary>
/// Dependency property for the <see cref="ClickedCommand"/> property.
/// </summary>
public static DependencyProperty ClickedCommandProperty = DependencyProperty.Register("ClickedCommand", typeof(string),
typeof(MyOldToolBarButton),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
#endregion
#region Variables.
// The default image source for the button glyph.
public Uri _defaultImageSource { private set; get; }
#endregion
#region Properties.
/// <summary>
/// Property to set or return the ID of the button.
/// </summary>
[Category("Configuration")]
public string ID
{
get
{
object value = GetValue(IDProperty);
return value == null ? string.Empty : value.ToString();
}
set
{
SetValue(IDProperty, value);
}
}
/// <summary>
/// Property to set or return the glyph for this button.
/// </summary>
[Category("Configuration")]
public ImageSource Glyph
{
get
{
return GetValue(GlyphProperty) as ImageSource;
}
set
{
SetValue(GlyphProperty, value);
}
}
/// <summary>
/// Property to set or return the tool tip for the button.
/// </summary>
///
[Category("Configuration")]
public string ToolTip
{
get
{
object value = GetValue(ToolTipProperty);
return value == null ? string.Empty : value.ToString();
}
set
{
SetValue(ToolTipProperty, value);
}
}
/// <summary>
/// Property to set or return whether the button is visible or not.
/// </summary>
///
[Category("Configuration")]
public bool IsVisible
{
get
{
return (bool)GetValue(IsVisibleProperty);
}
set
{
SetValue(IsVisibleProperty, value);
}
}
/// <summary>
/// Property to set or return whether the button is enabled or not.
/// </summary>
///
[Category("Configuration")]
public bool IsEnabled
{
get
{
return (bool)GetValue(IsEnabledProperty);
}
set
{
SetValue(IsEnabledProperty, value);
}
}
#endregion
#region Methods.
/// <summary>
/// Function to handle a change to the <see cref="GlyphProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Glyph_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// Function to handle a change to the <see cref="IsVisibleProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Visible_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// Function to handle a change to the <see cref="IsEnabledProperty"/>.
/// </summary>
/// <param name="sender">The sender of the event.</param>
/// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
private static void Enabled_Changed(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
// TODO
}
/// <summary>
/// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable" /> derived class.
/// </summary>
/// <returns>The new instance.</returns>
protected Freezable CreateInstanceCore()
{
return new MyOldToolBarButton();
}
#endregion
#region Constructor/Finalizer.
/// <summary>
/// Initializes a new instance of the <see cref="MyOldToolBarButton"/> class.
/// </summary>
/// <param name="buttonID">The ID of the button being clicked.</param>
/// <param name="defaultImageSource">The default image source URI for the glyph used by the button.</param>
internal void MyOldToolBarButton(string buttonID, string defaultImageSource)
{
ID = buttonID;
IsVisible = true;
IsEnabled = true;
ToolTip = string.Empty;
if (!string.IsNullOrWhiteSpace(defaultImageSource))
{
_defaultImageSource = new Uri(defaultImageSource, UriKind.Relative);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="MyOldToolBarButton"/> class.
/// </summary>
public void MyOldToolBarButton()
{
// This is here to keep the XAML designer from complaining.
}
#endregion
}
And adding it to another "parent" control... The properties look like this:
Is this what you are looking for?

ContentDialog do not subscribe to ICommand.CanExecuteChanged

I have a problem with Windows.UI.Xaml.Controls.ContentDialog. I want to disable it primary button when System.Windows.Input.ICommand.CanExecute return false. But it seem ContentDialog does not subscribe to ICommand.CanExecuteChanged event. I don't known why. This is my code:
NewTracingDialog.xaml
<ContentDialog
x:Class="RouterTracer.NewTracingDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RouterTracer"
xmlns:model="using:RouterTracer.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="NEW TRACING"
PrimaryButtonText="trace"
SecondaryButtonText="cancel"
PrimaryButtonCommand="{Binding}"
d:DataContext="{d:DesignInstance Type=model:NewTracingViewModel}">
<StackPanel VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<TextBox Name="destinationHost" Header="Destination Host" Text="{Binding Host, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Name="port" Header="UDP Port" InputScope="Number" Text="{Binding Port, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<TextBox Name="hopLimit" Header="Hop Limit" InputScope="Number" Text="{Binding HopLimit, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
</ContentDialog>
NewTracingViewModel.cs
//-----------------------------------------------------------------------
// <copyright file="NewTracingViewModel.cs">
// Copyright (c) Putta Khunchalee.
// </copyright>
// <author>Putta Khunchalee</author>
//-----------------------------------------------------------------------
namespace RouterTracer.ViewModels
{
using System;
/// <summary>
/// View model for new tracing dialog.
/// </summary>
public sealed class NewTracingViewModel : ExecutableViewModel
{
private byte hopLimit;
private string host;
private ushort port;
/// <summary>
/// Initialize a new instance of the <see cref="NewTracingViewModel"/> class.
/// </summary>
public NewTracingViewModel()
{
}
/// <summary>
/// Gets or sets TTL or Hop Limit.
/// </summary>
/// <value>
/// TTL or Hop Limit.
/// </value>
public byte HopLimit
{
get { return this.hopLimit; }
set { this.SetProperty(ref this.hopLimit, value, "HopLimit"); }
}
/// <summary>
/// Gets or sets destination host.
/// </summary>
/// <value>
/// Hestination host.
/// </value>
public string Host
{
get { return this.host; }
set { this.SetProperty(ref this.host, value, "Host"); }
}
/// <summary>
/// Gets or sets destination port.
/// </summary>
/// <value>
/// Destination port.
/// </value>
public ushort Port
{
get { return this.port; }
set { this.SetProperty(ref this.port, value, "Port"); }
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require data to be passed,
/// this object can be set to <c>null</c>.
/// </param>
public override void Execute(object parameter)
{
// This method get execute normally.
}
/// <summary>
/// Validate all properties to determine executable status.
/// </summary>
/// <returns>
/// <c>true</c> if instance can be execute; otherwise <c>false</c>.
/// </returns>
protected override bool ValidateProperties()
{
if (this.hopLimit == 0)
{
return false;
}
if (string.IsNullOrWhiteSpace(this.host))
{
return false;
}
if (this.port == 0)
{
return false;
}
return true;
}
}
}
ExecutableViewModel.cs
//-----------------------------------------------------------------------
// <copyright file="ExecutableViewModel.cs">
// Copyright (c) Putta Khunchalee.
// </copyright>
// <author>Putta Khunchalee</author>
//-----------------------------------------------------------------------
namespace RouterTracer.ViewModels
{
using System;
using System.Windows.Input;
/// <summary>
/// Base class for all View Model that executable via <see cref="ICommand"/>.
/// </summary>
public abstract class ExecutableViewModel : ViewModel, ICommand
{
private bool canExecute;
/// <summary>
/// Initialize a new instance of the <see cref="ExecutableViewModel"/> class.
/// </summary>
protected ExecutableViewModel()
{
}
/// <summary>
/// Occurs when changes occur that affect whether or not the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged;
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require data to be passed,
/// this object can be set to <c>null</c>.
/// </param>
/// <returns>
/// <c>true</c> if this command can be executed; otherwise, <c>false</c>.
/// </returns>
public bool CanExecute(object parameter)
{
return this.canExecute;
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">
/// Data used by the command. If the command does not require data to be passed,
/// this object can be set to <c>null</c>.
/// </param>
public abstract void Execute(object parameter);
/// <summary>
/// Invoked when status of <see cref="CanExecute(object)"/> has changed.
/// </summary>
protected virtual void OnCanExecuteChanged()
{
var handlers = this.CanExecuteChanged;
if (handlers != null)
{
handlers(this, EventArgs.Empty);
}
}
/// <summary>
/// Invoked when value of model's property has been changed.
/// </summary>
/// <param name="name">
/// Name of the property that value has changed.
/// </param>
protected override void OnPropertyChanged(string name)
{
base.OnPropertyChanged(name);
this.UpdateCanExecuteFlag(ValidateProperties());
}
/// <summary>
/// Validate all properties to determine executable status.
/// </summary>
/// <returns>
/// <c>true</c> if instance can be execute; otherwise <c>false</c>.
/// </returns>
protected abstract bool ValidateProperties();
/// <summary>
/// Update status of <see cref="CanExecute(object)"/>.
/// </summary>
/// <param name="canExecute">
/// <c>true</c> if instance can be execute; otherwise <c>false</c>.
/// </param>
private void UpdateCanExecuteFlag(bool canExecute)
{
if (this.canExecute == canExecute)
{
return;
}
this.canExecute = canExecute;
this.OnCanExecuteChanged();
}
}
}
ViewModel.cs
//-----------------------------------------------------------------------
// <copyright file="ViewModel.cs">
// Copyright (c) Putta Khunchalee.
// </copyright>
// <author>Putta Khunchalee</author>
//-----------------------------------------------------------------------
namespace RouterTracer.ViewModels
{
using System.ComponentModel;
/// <summary>
/// Base class for all View Model.
/// </summary>
public abstract class ViewModel : INotifyPropertyChanged
{
/// <summary>
/// Initialize a new instance of the <see cref="ViewModel"/> class.
/// </summary>
protected ViewModel()
{
}
/// <summary>
/// Raise when value of model's property has been changed.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Invoked when value of model's property has been changed.
/// </summary>
/// <param name="name">
/// Name of the property that value has changed.
/// </param>
protected virtual void OnPropertyChanged(string name)
{
var handlers = this.PropertyChanged;
if (handlers != null)
{
handlers(this, new PropertyChangedEventArgs(name));
}
}
/// <summary>
/// Change the value of the field that is property backed.
/// </summary>
/// <typeparam name="T">
/// Type of the field.
/// </typeparam>
/// <param name="field">
/// Field to change value.
/// </param>
/// <param name="value">
/// The new value.
/// </param>
/// <param name="name">
/// Name of backed property.
/// </param>
/// <returns>
/// <c>true</c> when value has been changed; otherwise <c>false</c>.
/// </returns>
protected bool SetProperty<T>(ref T field, T value, string name)
{
T previousValue;
// Check to see if value change is neccessary.
if (object.Equals(field, value))
{
return false;
}
// Change value.
previousValue = field;
field = value;
this.OnPropertyChanged(name);
return true;
}
}
}
Sorry for long codes. Thank you.
I have give up and use a workaround instead. Maybe it is not yet implemented in ContentDialog. This is my workaround.
NewTracingDialog.xaml.cs
//-----------------------------------------------------------------------
// <copyright file="NewTracingDialog.xaml.cs">
// Copyright (c) Putta Khunchalee.
// </copyright>
// <author>Putta Khunchalee</author>
//-----------------------------------------------------------------------
namespace RouterTracer
{
using System;
using System.Windows.Input;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
/// <summary>
/// Dialog for gather tracing information from user.
/// </summary>
public sealed partial class NewTracingDialog : ContentDialog
{
/// <summary>
/// Used to remove <see cref="OnDataContextCanExecuteChanged(object, EventArgs)"/> before
/// changing to the new data context.
/// </summary>
private ICommand currentDataContext;
/// <summary>
/// Initialize a new instance of the <see cref="NewTracingDialog"/> class.
/// </summary>
public NewTracingDialog()
{
this.InitializeComponent();
this.DataContextChanged += this.OnDataContextChanged;
}
/// <summary>
/// Invoke when executable flag of data context has changed.
/// </summary>
/// <param name="sender">
/// Data context that executable flag has changed.
/// </param>
/// <param name="e">
/// The empty <see cref="EventArgs"/>.
/// </param>
private void OnDataContextCanExecuteChanged(object sender, EventArgs e)
{
this.IsPrimaryButtonEnabled = ((ICommand)sender).CanExecute(null);
}
/// <summary>
/// Invoke when data context has been changed.
/// </summary>
/// <param name="sender">
/// The instance of <see cref="NewTracingDialog"/> that data context has changed.
/// </param>
/// <param name="args">
/// Event informations.
/// </param>
private void OnDataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
// Get a new data context.
var command = (ICommand)args.NewValue;
if (command == null)
{
return;
}
// Disable primary button if data context is not executable.
this.IsPrimaryButtonEnabled = command.CanExecute(null);
// Subscribe to data context executable changed event.
if (this.currentDataContext != null)
{
this.currentDataContext.CanExecuteChanged -= this.OnDataContextCanExecuteChanged;
}
command.CanExecuteChanged += this.OnDataContextCanExecuteChanged;
this.currentDataContext = command;
}
}
}

Why is passed object null? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I Pass an object OptionSelector to a different ViewModel. When passing it is not null. But on the receiving end it shows as null. Any ideas
My View is wrapped in this class.
public class CoreView : XboxApplicationPage, IRefAppNavigationItem
{
/// <summary>
/// Gets or sets navigation data for nested views.
/// </summary>
public object Data
{
get { return GetValue(DataProperty) as object; }
set { SetValue(DataProperty, value); }
}
/// <summary>
/// Identifies the Data dependency property.
/// </summary>
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data",typeof(object),typeof(CoreView),new PropertyMetadata(null));
/// <summary>
/// Gets or sets the viewModel used in this page.
/// </summary>
public CoreViewModel ViewModel
{
get
{
return (CoreViewModel)GetValue(ViewModelProperty);
}
set { SetValue(ViewModelProperty, value); }
}
/// <summary>
/// Sets the View.DataContext to the View.ViewModel.
/// </summary>
private void SetViewModel()
{
if (ViewModel != null)
{
try
{
if (this.Data != null)
{
ViewModel.Data = this.Data;
}
else
{
ViewModel.Data = this.Tag;
}
SetDataContext();
}
catch(Exception e)
{
Logger.Log("SetViewModel() error :" + e.StackTrace);
}
}
}
/// <summary>
/// Sets the DataContext to the ViewModel.
/// Override when additional actions might be required after setting the DataContext.
/// </summary>
protected virtual void SetDataContext()
{
this.DataContext = ViewModel;
}
/// <summary>
/// Handles on NavigateTo events.
/// </summary>
/// <param name="e">Event args.</param>
/// <remarks>This method is used to get the post navigation data and integrate into CoreView.</remarks>
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (DesignerProperties.IsInDesignTool)
{
return;
}
try
{
if (this.currentPageCulture != AmebaTV_XBOXApplication.Common.Resources.Localization.CurrentCulture)
{
UpdateLocalizedStrings(this);
}
Microsoft.Xbox.Controls.Localization.CultureChanged += Localization_CultureChanged;
var postNavigationState = IoC.Get<INavigationService>().GetPostNavigationData(NavigationContext);
if (postNavigationState != null)
{
this.Data = postNavigationState;
}
this.ViewModel.OnNavigatedTo();
if (legendService != null)
{
legendService.IsNavigateBackEnabled = true;
}
base.OnNavigatedTo(e);
}
catch (Exception ex)
{
Logger.Log("OnNavigatedTo : "+ex.Message);
}
}
}
/// <summary>
/// Base class for all ViewModels.
/// </summary>
public class CoreViewModel : ViewModelBase
{
/// <summary>
/// Field for Data.
/// </summary>
private object data;
/// <summary>
/// To be used with navigation to populate view models with initial content.
/// </summary>
public virtual void OnDataSet()
{
}
/// <summary>
/// Gets or sets ViewModel data.
/// </summary>
public object Data
{
get { return this.data; }
set
{
this.data = value;
RaisePropertyChanged("Data");
OnDataSet();
}
}
}
OptionSelectorData object
/// <summary>
/// Contains data for the options selector view.
/// </summary>
public class OptionSelectorData
{
/// <summary>
/// Gets or sets the list of options.
/// </summary>
public IList<string> Options { get; set; }
/// <summary>
/// Gets or sets the option title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the callback that will be invoked when an option is selected
/// </summary>
public Action<string> NotificationCallback { get; set; }
}
}
Command to trigger navigation
public class MoreOverflowViewModel : CoreViewModel
{
/// <summary>
/// Navigate to Property filter page
/// </summary>
public ICommand gotoViewPagebyCriteria
{
get
{
return new RelayCommand(() =>
{
OptionSelectorData option = new OptionSelectorData
{
Options = filterOptions, Title =
Localization.GetByLocalizationKey("OptionTitleFilter"),
NotificationCallback = OnFilterOptionsCallback
};
Messenger.Default.Send(new NavigateToMessage(new
Uri(PageListings.ViewPageByCriteria, UriKind.Relative), option));
});
}
}
}
Viewmodel to receive data, OnDataSet checks object and sets properties
public class ViewByCriteriaViewModel : CoreViewModel
{
/// <summary>
/// ondataset
/// </summary>
public override void OnDataSet()
{
option = this.Data as OptionSelectorData;
if (option != null)
{
OptionTitle = option.Title;
itemsSource = option.Options;
}
else
{
Logger.Log("NULL Option Data");
}
}
}
Try this. I'm thinking that this.Data isn't getting the object you think it is. If it's some other type, then as will return null.
public override void OnDataSet()
{
Logger.Log("this.Data = " + (this.Data == null ? "null" : this.Data.GetType().Name));
option = this.Data as OptionSelectorData;
if (option != null)
{
OptionTitle = option.Title;
itemsSource = option.Options;
}
else
{
Logger.Log("NULL Option Data");
}
}
Its seems I had a default OnNavigatedTo() that was overriding the method in the base class. Issue resolved.

Categories