I'm having some issues updating a dependency property from a standard property.
If I set the property to null or update it with new data I was under the impression that it would reset the dependency property. However it looks as tho it just piles the new data on top.
Here's a couple of properties / dependency properties I'm using:
Dependency Properties
public static readonly DependencyProperty DataTableChartProperty = DependencyProperty.Register
("DataTableChart", typeof(DataTable), typeof(MainWindowViewModel));
public static readonly DependencyProperty ContentElementProperty = DependencyProperty.Register
("ContentElement", typeof(FrameworkElement), typeof(MainWindowViewModel));
Standard Properties
public DataTable DataTableChart
{
get { return (DataTable)this.GetValue(DataTableChartProperty); }
set { this.SetValue(DataTableChartProperty, value); }
public FrameworkElement ContentElement
{
get { return (FrameworkElement)this.GetValue(ContentElementProperty); }
set { this.SetValue(ContentElementProperty, value); }
}
I would greatly appreciate any suggestions. Thanks in Advance!
This is how I'm setting it for now... for testing...
void _bw_DoWork(object sender, DoWorkEventArgs e)
{
var loadLog = new LoadLog();
e.Result = loadLog.LoadCaseLogs(SelectedFiles);
}
void _bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
DataTableChart = null;
ContentElement = null;
ContentElement = blah;
DataTableResult = e.Result as DataTable;
DataTableChart = caseData.LoadUserData(DataTableResult);
LoadingScreen = false;
}
public ChartControl blah = new ChartControl();
Dependency properties are cleared using the ClearValue method, setting it to null is just setting it to null, which is not the same.
Related
I want to bind two Dependency Property, both in one instance of object or different instance of object or different type of instance of object.
So, i read the docs:
https://learn.microsoft.com/en-us/dotnet/desktop/wpf/data/how-to-create-a-binding-in-code?view=netframeworkdesktop-4.8
But i see the method is:
Set source:
set Path string which is a name of instance property with user defined type
set that source instance of object which contain that property which have that name
Set destination:
set destination instance of destination dependency property
set real static dependency property
So, my question is: Is exists any method to set two Dependency Property bind look like this:
SetBindingMethod(sourceInstanceOfObject, sourceDependencyProperty, destinationInstanceOfObject, destinationDependencyProperty)
Here is my test code is working, but not that what i want:
class TestClass : DependencyObject
{
public int Int0
{
get { return (int)GetValue(Int0Property); }
set { SetValue(Int0Property, value); }
}
public int Int1
{
get { return (int)GetValue(Int1Property); }
set { SetValue(Int1Property, value); }
}
public static readonly DependencyProperty Int0Property =
DependencyProperty.Register(nameof(Int0), typeof(int), typeof(TestClass), new PropertyMetadata(0, new PropertyChangedCallback(Int0Changed)));
public static readonly DependencyProperty Int1Property =
DependencyProperty.Register(nameof(Int1), typeof(int), typeof(TestClass), new PropertyMetadata(0, new PropertyChangedCallback(Int1Changed)));
private static void Int0Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Int0 changed: " + e.NewValue);
}
private static void Int1Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Console.WriteLine("Int1 changed: " + e.NewValue);
}
internal void Test()
{
while(true)
{
Thread.Sleep(500);
Int0 += 1;
Thread.Sleep(500);
Int1 -= 1;
}
}
public TestClass()
{
Binding binding = new Binding(nameof(Int0));
binding.Source = this;
binding.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(this, Int1Property, binding);
}
}
I hope that is clear, i'm on my limit of my english features :)
br: ExtSol
I have the following class:
public class dm_fourvalues : DependencyObject
{
[JsonProperty]
public double First
{
get { return (double)GetValue(FirstProperty); }
set
{
SetValue(FirstProperty, value);
}
}
public static readonly DependencyProperty FirstProperty =
DependencyProperty.Register("First", typeof(double), typeof(dm_fourvalues),
new FrameworkPropertyMetadata(1d,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(OnFirstPropertyChanged)));
private static void OnFirstPropertyChanged(DependencyObject sender,
DependencyPropertyChangedEventArgs e)
{
dm_fourvalues uci = sender as dm_fourvalues;
if (uci != null)
{
uci.OnFirstChanged();
}
}
private void OnFirstChanged()
{
Console.WriteLine("first on dm fourvalues changed");
}
Now if use this class as identical property on another object, when the First property gets changed,
this object's OnChanged is not triggered, thus also a binding would not work.
What defines that a parent dependencyobject has been changed?
I have two dependency properties and when value in First changes, I would like to update also the Second - for example give it temporary value and update UI, but I don't want to break the binding on Second property.
public bool Frist
{
get { return (bool)GetValue(FristProperty); }
set { SetValue(FristProperty, value); }
}
public static readonly DependencyProperty FristProperty =
DependencyProperty.Register("Frist", typeof(bool), typeof(ItemControl), new PropertyMetadata(false, FirstUpdated));
private static void FirstUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var theControl = d as ItemsControl;
// I would like to update also second dependency property here
// for example if First == true, then Second = Overriden
// else Second = the value from binding
}
public string Second
{
get { return (string)GetValue(SecondProperty); }
set { SetValue(SecondProperty, value); }
}
public static readonly DependencyProperty SecondProperty =
DependencyProperty.Register("Second", typeof(string), typeof(ItemsControl), new PropertyMetadata(string.Empty));
I've taken a look at various samples from WPF, but seems like there are missing things in UWP. What are the options?
I have a class called TxtBox with an attached Property:
public class TxtBox
{
public static readonly DependencyProperty TypeProperty = DependencyProperty.RegisterAttached(
"Type", typeof (Enums.FieldType), typeof (TextBox), new PropertyMetadata(default(Enums.FieldType),OnTypeChanged));
public static void SetType(DependencyObject element, Enums.FieldType value)
{
element.SetValue(TypeProperty, value);
}
public static Enums.FieldType GetType(DependencyObject element)
{
return (Enums.FieldType) element.GetValue(TypeProperty);
}
private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var src = (TextBox) d; //(FrameworkElement)d;
var binding = BindingOperations.GetBinding(src, TextBox.TextProperty);
if (binding != null) //Binding here is always null ?????????
{
binding.Converter = new NumberConverter();
binding.ConverterParameter = e.NewValue;
}
}
}
At MainWindow.xaml :
<Grid Margin="10">
<TextBox Text="{Binding RequestNo}" att:TxtBox.Type="Number" />
<\Grid>
I need to assign the Converter and ConverterParameter for the TextProperty once I have set the type for the textbox control through the attached property (Type). When the OnTypeChanged method fires, I can't get the Binding, as it is always null !!!
Thanks in advance :)
Your attached property is being set before the Binding is applied to the Text property of the Text box. You can work around this by attempting to update the Binding when the value of Text changes:
private static void OnTypeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var src = (TextBox)d;
var dpd = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));
dpd.AddValueChanged(src, UpdateBindingHandler);
UpdateBinding(src);
}
protected static void UpdateBindingHandler(object sender, EventArgs e)
{
UpdateBinding((TextBox)sender);
}
private static void UpdateBinding(TextBox tbox)
{
var binding = BindingOperations.GetBinding(tbox, TextBox.TextProperty);
if (binding != null)
{
binding.Converter = new NumberConverter();
binding.ConverterParameter = GetType(tbox);
var dpd = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof(TextBox));
// Don't do this every time the value changes, only the first time
// it changes after TxtBox.Type has changed.
dpd.RemoveValueChanged(tbox, UpdateBindingHandler);
}
}
When you do that, you'll find that your whole design is flawed: You can't alter a Binding once it's been used. It throws an exception.
You might be able to get away with creating a new binding, clone the properties of the old one, and put a converter on it. Bindings have a lot of properties, though, and if there's already a converter, you'll need to replace it with a chain converter that preserves that one while adding yours.
I'm not sure this feature is going to work out.
Finally,I have got the solution, I changed the design as Mr Peter Duniho advised me to write a markup extension to take the place of the {Binding}
public class TextBoxTypeExtension:MarkupExtension
{
private readonly Binding _binding;
public TextBoxTypeExtension(Binding binding,Enums.FieldType type)
{
_binding = binding;
_binding.Converter = new NumberConverter();
_binding.ConverterParameter = type;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return _binding.ProvideValue(serviceProvider);
}
}
At MainWindow.xaml :
<TextBox MaxLength="10" Grid.Row="1" Grid.Column="1"
Text="{extension:TextBoxType {Binding Request.RequestNo},Number}"/>
Reference:
MarkupExtension that uses a DataBinding value
In developing some UserControls for internal use I followed this exmaple from MSDN http://msdn.microsoft.com/en-us/library/vstudio/ee712573(v=vs.100).aspx
The public value of one control is used by another control. The way I have this working currently is hooking into an event that is fired in the first control through code-behind. I am thinking that making one or both of the properties DependencyProperties which would eliminate the need for the code-behind.
public partial class UserControl1 : UserControl
{
private DataModel1 dm;
public UserControl1()
{
this.DataContext = new DataModel1();
dm = (DataModel1)DataContext;
InitializeComponent();
}
public DataValue CurrentValue
{
get { return dm.CurrentValue; }
set { dm.CurrentValue = value; }
}
}
public class DataModel1 : INotifyPropertyChanged
{
private DataValue _myData = new DataValue();
public DataValue CurrentValue
{
get { return _myData; }
set { if (_myData != value) {_myData = value OnPropertyChanged("CurrentValue"); }
}
// INotifyPropertyChanged Section....
}
The property is just a pass through from the DataModel1 class.
Both UserControls are very similar in their structure and have the same public properties. I would like to replace the code behind eventhandler with a Binding similar, I think to:
<my:UserControl1 Name="UserControl1" />
<my:UserControl2 CurrentValue={Binding ElementName="UserControl1", Path="CurrentValue"} />
but the standard examples of DependencyProperties have getters and setter that use the GetValue and SetValue functions which use a generated backing object instead of allowing a pass through.
public DataValue CurrentValue
{
get { return (DataValue)GetValue(CurrentValueProperty); }
set { SetValue(CurrentValueProperty, value); }
}
I think the DP should look like:
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(DataValue), typeof(UserControl1));
How can I change the definition of the public backing property to support the databinding pass through?
I found that jumping into the OnPropertyChanged event allowed me to pass the data through to the DataModel1. I am not 100% sure that this is the correct answer but it gets the job done.
Here is the corrected code:
public static readonly DependencyProperty CurrentValueProperty =
DependencyProperty.Register("CurrentValue", typeof(DataValue), typeof(UserControl1),
new PropertyMetadata(new PropertyChangedCallback(OnCurrenValueChanged)));
private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
UserControl1 uc = d as UserControl1;
if (e.NewValue != null)
{
uc.dm.CurrentValue = e.NewValue as DataValue;
}
}
public DataValue CurrentValue
{
get { return GetValue(CurrentValueProperty) as DataValue; }
set { SetValue(CurrentValueProperty, value); }
}