Change non static object from static Context - c#

I have next dependecy property:
public static DependencyProperty IsInReadModeProperty =
DependencyProperty.Register("IsInReadMode", typeof(bool),
typeof(RegCardSearchForm), new PropertyMetadata(false, ReadModeChanged));
and I have next method which handle Property changed event:
public static void ReadModeChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
btnSearch.Visibility = Visibility.Collapsed;
btnExport.Visibility = Visibility.Collapsed;
cbExportWay.Visibility = Visibility.Collapsed;
}
}
But compiler give me error that i cannot acces non static buttons (btnSearch and e.t.c ) in static context.
I want change visibility of buttons when property value changed. How can I resolve this situation?

Since (non-attached) DependencyProperties are restricted to being set on their owner type you can just create an instance method to hold your logic and call that from the static method by casting the DependencyObject:
public static readonly DependencyProperty IsInReadModeProperty = DependencyProperty.Register(
"IsInReadMode",
typeof(bool),
typeof(RegCardSearchForm),
new UIPropertyMetadata(false, ReadModeChanged));
private static void ReadModeChanged(DependencyObject dObj, DependencyPropertyChangedEventArgs e)
{
RegCardSearchForm form = dObj as RegCardSearchForm;
if (form != null)
form.ReadModeChanged((bool)e.OldValue, (bool)e.NewValue);
}
protected virtual void ReadModeChanged(bool oldValue, bool newValue)
{
// TODO: Add your instance logic.
}

One way could be to extend a class from DependencyObject that would contain the set/get of the controls that you want to manipulate. And process it in ReadModeChanged event by accessing DependencyObject.
This example might help.
... example derives from DependencyObject to create a new abstract class. The class then registers an attached property and includes support members for that attached property.

If ReadModeChanged is a static method of the container for your buttons, then just make it an instance method of the container.

These things do have to be static in order for a DependencyProperty to work properly However, the parameter to your PropertyChanged handler is probably the thing you need: it's the instance whose property has just changed. I suspect this would work for you:
public static void ReadModeChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
RegCardSearchForm c = (RegCardSearchForm)d;
c.btnSearch.Visibility = Visibility.Collapsed;
c.btnExport.Visibility = Visibility.Collapsed;
c.cbExportWay.Visibility = Visibility.Collapsed;
}
}

Related

Convert to DependencyProperty

I have a question, someone could help transform this code (used in codebehind ) for use by dependyProperty ?
This code gives the focus to the first item of listview . THX!!!!!!
private void ItemContainerGeneratorOnStatusChanged(object sender, EventArgs eventArgs)
{
if (lvResultado.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
var index = lvResultado.SelectedIndex;
if (index >= 0)
{
var item = lvResultado.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
if (item != null)
{
item.Focus();
}
}
}
}
Specifically, I want to write something like: local:FocusFirstElement.Focus="True" in my XAML instead of writing this code for every list view.
What you are is really an attached behavior, which is implemented via an attached property which is really a special dependency property (which you seem to have hit upon already).
First, create an attached property. This is most easliy accomplished using the propa snippet:
public static bool GetFocusFirst(ListView obj)
{
return (bool)obj.GetValue(FocusFirstProperty);
}
public static void SetFocusFirst(ListView obj, bool value)
{
obj.SetValue(FocusFirstProperty, value);
}
public static readonly DependencyProperty FocusFirstProperty =
DependencyProperty.RegisterAttached("FocusFirst", typeof(bool),
typeof(ListViewExtension), new PropertyMetadata(false));
I'm assuming this is in a static class called ListViewExtenstion. Then, handle the property changed event:
public static readonly DependencyProperty FocusFirstProperty =
DependencyProperty.RegisterAttached("FocusFirst", typeof(bool),
typeof(ListViewExtension), new PropertyMetadata(false, HandleFocusFirstChanged));
static void HandleFocusFirstChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
}
In that handler you would check the current value (in e) and register or deregister for the appropriate event on the ListView contained in depObj. Then you would use your existing code to set the focus. Something like:
static void HandleFocusFirstChanged(
DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
ListView lv = (ListView)debObj;
if ((bool)e.NewValue)
lv.StatusChanged += MyLogicMethod;
}

WPF - GetBindingExpression in PropertyChangedCallback of DependencyProperty

I need to be able to access the binding expression for the Text property of a TextBox from within a DependencyProperty on a TextBox. the value of my DependencyProperty is set in XAML. I'm calling GetBindingExpression in the PropertyChangedCallback method of my DependencyProperty, but I'm too early at this point because GetBindingExpression always returns null here, yet after the window fully loads it definitely returns a value (I tested using a button on screen to change the value of my DependencyProperty).
Clearly I have a load order issue here where my DependencyProperty's value is set before the Text property is bound to my view model. My question is, is there some event I can hook into to identify when the binding of the Text property is complete? Preferably without modifying the XAML of my TextBox as I have hundreds of them in the solution.
public class Foobar
{
public static readonly DependencyProperty TestProperty =
DependencyProperty.RegisterAttached(
"Test", typeof(bool), typeof(Foobar),
new UIPropertyMetadata(false, Foobar.TestChanged));
private static void TestChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
var textBox = (TextBox)o;
var expr = textBox.GetBindingExpression(TextBox.TextProperty);
//expr is always null here, but after the window loads it has a value
}
[AttachedPropertyBrowsableForType(typeof(TextBoxBase))]
public static bool GetTest(DependencyObject obj)
{
return (bool)obj.GetValue(Foobar.TestProperty);
}
[AttachedPropertyBrowsableForType(typeof(TextBoxBase))]
public static void SetTest(DependencyObject obj, bool value)
{
obj.SetValue(Foobar.TestProperty, value);
}
}
Try listen to LayoutUpdated event. I think its called layout updated event. Else google it. Its a crazy little event which will be fired everytime no matter what you do ex. when loading, drawing, even when you move your mouse!
Take a look at this pseudo code:
private static void TestChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
var textBox = (TextBox)o;
// start listening
textBox.LayoutUpdated += SomeMethod();
}
private static void SomeMethod(...)
{
// this will be called very very often
var expr = textBox.GetBindingExpression(TextBox.TextProperty);
if(expr != null)
{
// finally you got the value so stop listening
textBox.LayoutUpdated -= SomeMethod();

Update dependency property when child property has been updated

I have a class inheriting canvas with the following dependency property
public class StorageCanvas : Canvas
{
public readonly static DependencyProperty StorageProperty = DependencyProperty.Register(
"Storage",
typeof(Polygon),
typeof(StorageCanvas));
public Polygon Storage
{
get { return (Polygon) GetValue(StorageProperty); }
set { SetValue(StorageProperty, value); }
}
}
Can I somehow make the dependency property "update" when the Storage polygon Points has been altered/updated, instead of requiring the polygon to be replaced with a new instance?
Well Polygon.Points is a PointCollection, so you could just subscribe to the Changed event of it and then call InvalidateVisual() as suggested by #dowhilefor
public class StorageCanvas : Canvas {
public static readonly DependencyProperty StorageProperty = DependencyProperty.Register(
"Storage",
typeof(Polygon),
typeof(StorageCanvas),
new FrameworkPropertyMetadata(null, PropertyChangedCallback));
public Polygon Storage {
get {
return (Polygon)GetValue(StorageProperty);
}
set {
SetValue(StorageProperty, value);
}
}
private static void PropertyChangedCallback(
DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args) {
var currentStorageCanvas = dependencyObject as StorageCanvas;
if (currentStorageCanvas == null)
return;
var oldPolygon = args.OldValue as Polygon;
if (oldPolygon != null)
oldPolygon.Points.Changed -= currentStorageCanvas.PointsOnChanged;
var newPolygon = args.NewValue as Polygon;
if (newPolygon == null)
return;
newPolygon.Points.Changed += currentStorageCanvas.PointsOnChanged;
// Just adding the following to test if updates are fine.
currentStorageCanvas.Children.Clear();
currentStorageCanvas.Children.Add(newPolygon);
}
private void PointsOnChanged(object sender, EventArgs eventArgs) {
InvalidateVisual();
}
}
So now if any individual Point in Storage changed, without actually recreating the entire object, InvalidateVisual() will be fired.
The concept is just about subscribing to the Changed event of PointsCollection. Whether it's the right thing to do for you is a question you need to address yourself based on your requirements and logic.
Register the dependency property with Affects render meta data option.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkpropertymetadata.affectsrender.aspx

Silverlight detect when Dependency property has a Xaml binding

Is it possible to detect when a Xaml binding is set on a DependencyProperty in Silverlight?
E.g. if I had a custom user-control with single dependency property and a binding declared like this:
public class MyControl : UserControl
{
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test",
typeof(object), typeof(MyControl),
new PropertyMetadata(null));
public object Test
{
get { return GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
}
<MyControl Test="{Binding APropInViewModel}>
</MyControl>
Can I in the MyControl code to something like this?
// Ctor
public MyControl()
{
TestProperty.BindingChanged += new EventHandler(...)
}
e.g. can I get a notification of binding?
NOTE:
This is to solve a tricky order of precedence problem, described here so just checking for new values in the DependencyPropertyChanged handler won't work - because the property changed handler doesn't fire!!
It is possible for value changes in this binding. You can detect changes using propertychanged callback method which is static for Dependency properties.
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register("Test",
typeof(object), typeof(MyControl),
new PropertyMetadata(null, TestChangedCallbackHandler));
private static void TestChangedCallbackHandler(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
MyControl obj = sender as MyControl;
Test = args.NewValue;
}
However, this might cause following event listening cases. If you want to listen changes on this dependency property is explained in this link :
Listen DepencenyProperty value changes
public void RegisterForNotification(string propertyName, FrameworkElement element, PropertyChangedCallback callback)
{
Binding b = new Binding(propertyName) { Source = element };
var prop = System.Windows.DependencyProperty.RegisterAttached(
"ListenAttached" + propertyName,
typeof(object),
typeof(UserControl),
new System.Windows.PropertyMetadata(callback));
element.SetBinding(prop, b);
}
and call like this
this.RegisterForNotification("Test", this, TestChangedCallback);

override itemsource property in listbox c#.net

i m inheriting ListBox to my class and i want to override itemsource property.
i actually want to do someoperation when itemsource is assigned.
how it is possible?
i want in c# code only not in xaml
The way you override a dependency property in WPF is this way....
public class MyListBox : ListBox
{
//// Static constructor to override.
static MyListBox()
{
ListBox.ItemsSourceProperty.OverrideMetadata(typeof(MyListBox), new FrameworkPropertyMetadata(null, MyListBoxItemsSourceChanged));
}
private static void MyListBoxItemsSourceChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
var myListBox = sender as MyListBox;
//// You custom code.
}
}
Is this what you are looking for?
Why not just set SourceUpdated event handler before setting the item source property?
For Example if MyListBox is your Listbox & MyItemSource is the source, you may set event handler n call it as follows:
void MyFunction()
{
MyListBox.SourceUpdated += new EventHandler<DataTransferEventArgs>(MyListBox_SourceUpdated);
MyListBox.ItemsSource = MyItemSource;
}
void MyListBox_SourceUpdated(object sender, DataTransferEventArgs e)
{
// Do your work here
}
Also, make sure that your data source implements INotifyPropertyChanged or INotifyCollectionChanged events.
Here i have crated a Custom List box which extends from Listbox and it got a dependency property itemssource...
When ever item source got updated you can do your operations and after that you can call the updatesourcemethod of customlistbox which will assign the itemsSource property of BaseClass.
public class CustomListBox : ListBox
{
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for ItemsSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(CustomListBox), new UIPropertyMetadata(0, ItemsSourceUpdated));
private static void ItemsSourceUpdated(object sender, DependencyPropertyChangedEventArgs e)
{
var customListbox = (sender as CustomListBox);
// Your Code
customListbox.UpdateItemssSource(e.NewValue as IEnumerable);
}
protected void UpdateItemssSource(IEnumerable source)
{
base.ItemsSource = source;
}
}

Categories