I need some help!
I have build a custom control and added to it a DependencyProperty of type:
Dictionary<string,int>
and from the XAML where the control is held I do a data binding to bind to the Dictionary outside the control.
here are some code snippets:
View model of the control who hold the custom control
private Dictionary<string, int> _wordsList;
public Dictionary<string, int> WordsList
{
get
{
return _wordsList;
}
set
{
_wordsList = value;
RaisePropertyChanged("WordsList");
}
}
public WordsViewModel()
{
//CalculateWordsDictionary returns a dictionary<string,int>
WordsList = CalculateWordsDictionary(texts);
}
XAML:
<local:MyControl WordsList="{Binding Path=WordsList}" />
Code behind of the custom control:
public Dictionary<string, int> WordsList
{
get { return (Dictionary<string, int>)GetValue(WordsListProperty); }
set { SetValue(WordsListProperty, value); }
}
// Using a DependencyProperty as the backing store for WordsList. This enables animation, styling, binding, etc...
public static readonly DependencyProperty WordsListProperty =
DependencyProperty.Register("WordsList", typeof(Dictionary<string, int>), typeof(MyControl), new PropertyMetadata(new Dictionary<string, int>()));
I've set a break point on the set of the DependencyProperty and it never reaches this point.
I just can't figure out why this isn't working... or maybe there is some other way to pass the dictionary to the control?
btw
I am using MVVM Light
the important stuff you did not post:) whats your binding within your usercontrol? you have to use some kind of "local binding" so that your MyControl binds to it dependency property. you can use ElementName binding like this:
EDIT: here is the code for the UserControl called MyControl (just a snippet)
<MyControl x:Name=uc>
<ContentControl Content="{Binding ElementName=uc, Path=WordsList}"/>
Fixed!!!!!
All the comments together was the question
I there was a DataContext defined, I removed it completely. Also I registered the property changed callback
worked as charm!
Thanks to all
Related
I know that I can declare a new DependencyProperty as such:
public String PropertyPath
{
get { return (String)GetValue(PropertyPathProperty); }
set { SetValue(PropertyPathProperty, value); }
}
public static readonly DependencyProperty PropertyPathProperty =
DependencyProperty.Register(nameof(PropertyPath), typeof(String),
typeof(NotEmptyStringTextBox),
new FrameworkPropertyMetadata(PropertyPath_PropertyChanged));
protected static void PropertyPath_PropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var ctl = d as NotEmptyStringTextBox;
var binding = new Binding(ctl.PropertyPath)
{
ValidationRules = { new NotEmptyStringRule() },
// Optional. With this, the bound property will be updated and validation
// will be applied on every keystroke.
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
};
ctl.StringBox.SetBinding(TextBox.TextProperty, binding);
}
But then the UserControl can only recieve a string with the name of the property to bind, and bind to it.
What I would like is to be able to have the same kind of comportment as "classical" properties, which you can either bind to, or give a static value.
My usage would be a boolean that modifies the display state of a UserControl, either statically with a fixed value or dynamically with a binding, all depending on the use case.
Maybe the way I made my dependency Property in the first place is incorrect, but here is how I can use it:
<inputboxes:NotEmptyStringTextBox
Grid.Column="1"
PropertyPath="Name"/>
This will bind the "Name" property from the DataContext, but I can't use it with a raw string, as it will make a BindingExpression error: "property not found"
EDIT:
I now have tried the following:
public bool Test
{
get { return (bool)GetValue(TestProperty); }
set { SetValue(TestProperty, value); }
}
public static readonly DependencyProperty TestProperty =
DependencyProperty.Register(nameof(Test), typeof(bool),
typeof(DamageTemplateListEditableUserControl));
I declared this new property, but I still cannot bind anything to it, only raw values are accepted
You shouldn't create a new binding in the callback. In fact, you don't need any callback at all.
Rename the dependency property to something better like "Text" and just bind the Text property of StringBox to the current value of your dependency property like this:
<TextBox x:Name="StringBox"
Text="{Binding Text, RelativeSource={RelativeSource AncestorType=local:NotEmptyStringTextBox},
UpdateSourceTrigger=PropertyChanged}" />
You can then set or bind the dependency property as usual.
If you really want a "PropertyPath" property, it shouldn't be a dependency property that you can bind something to but rather a simple CLR property that you can set to a string that represents a name of a property to bind to.
This is for example how the DisplayMemberPath property of an ItemsControl is implemented.
I am creating a Charting application using SciChart.
I have added a chart modifier class which allows editing of the chart data but only the data currently displayed. I need to extend this class so that the full ObservableCollection of each XyDataSeries can be accessed.
I have implemented an attached property which I can bind to in the MainWindow DataContext however whenever I run the application the collection is showing as null in the modifier class. Please can you advise. Thanks
public class MoveBlockModifier : ChartModifierBase
{
public static readonly DependencyProperty XyFGDataProperty = DependencyProperty.RegisterAttached("XyFGData", typeof(ObservableCollection<XyDataSeries<double,double>>), typeof(MoveBlockModifier), new FrameworkPropertyMetadata(new ObservableCollection<XyDataSeries<double,double>>()));
public ObservableCollection<XyDataSeries<double, double>> XyFGData
{
get { return (ObservableCollection < XyDataSeries<double, double>>)GetValue(XyFGDataProperty); }
set { SetValue(XyFGDataProperty, value); }
}
public MoveBlockModifier()
{
_ghostSeries = new FastLineRenderableSeries()
{
Stroke = Colors.Black,
DataSeries = editingSeries,
Name = "GhostSeries",
StrokeThickness = 1,
Opacity = 0.75,
};
}
}
Public Class MainWindow: Window, INotifyPropertyChanged
{
private ObservableCollection<XyDataSeries<double, double>> _xyFGData;
public ObservableCollection<XyDataSeries<double, double>> XYFGData
{
get { return _xyFGData; }
set { _xyFGData = value; OnPropertyChanged("XYFGData"); }
}
}
XAML of MainWindow
<s:SciChartSurface x:Name="Chart2">
<s:SciChartSurface.ChartModifier>
<local:MoveBlockModifier FixStart="{Binding FixStart}" FixEnd="{Binding FixEnd}"
IsEnabled="{Binding ChartTwoMoveBlockEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
XyFGData="{Binding XYFGData, Mode=TwoWay}" />
</s:ModifierGroup>
</s:SciChartSurface.ChartModifier>
</s:SciChartSurface>
The question above seems incomplete / has some errors. You mention an attached property, which you define as this
public static readonly DependencyProperty XyFGDataProperty = DependencyProperty.RegisterAttached("XyFGData", typeof(ObservableCollection<XyDataSeries<double,double>>), typeof(MoveBlockModifier), new FrameworkPropertyMetadata(new ObservableCollection<XyDataSeries<double,double>>()));
public ObservableCollection<XyDataSeries<double, double>> XyFGData
{
get { return (ObservableCollection < XyDataSeries<double, double>>)GetValue(XyFGDataProperty); }
set { SetValue(XyFGDataProperty, value); }
}
...
but this isn't the way to define attached properties in WPF. Follow the MSDN documentation for how to register an attached property.
Secondly, you define a default value of new ObservableCollectionXyDataSeries<double, double> in your FrameworkPropertyMetadata, but this is a bad idea, because you will share one instance of ObservableCollectionXyDataSeries<double, double> statically across all instances of MoveBlockModifier. Have a look at Where to initialize reference type dependency properties for a custom control?
Lastly its an attached property that you want to define but in XAML you are not using it like an attached property.
This part:
is incorrect. See how an attached property is attached in XAML here.
Finally you bind MoveBlockModifier.XyFGData to a property XYFGData in your main window but the DataContext of the MoveBlockModifier might not be MainWindow.
I suggest starting again and fixing these errors!
The propertychanged trigger in a viewmodel of a UWP app with Template10 is triggered by by the following way:
public var Thing{ get { return thing; } set { Set(ref thing, value); } }
The Set function is placed in the class bindableBase.
How can I use this same function in a Usercontrol?
I tried the folowing, but that didn't work:
BindableBase x;
var foo;
public var Foo{ get { return foo; } set { x.Set(ref foo, value); } }
you don't use in that fashion you use with a viewmodel for example if the Page you place the usercontrol would have a property associated with populating the fields of the usercontrol part of the viewmodel that is bound to the DataContext of the Page. I think you need to review MVVM. Or the viewmodel could be the DataContext of the userControl in question.
When creating a UserControl you'll want to use a DependencyProperty to create bindable properties. It's required to make them behave as expected when using the UserControl inside of an other control (like a Page). DependencyProperties are defined like this:
public int MyProperty
{
get { return (int)GetValue(MyPropertyProperty); }
set { SetValue(MyPropertyProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyPropertyProperty =
DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new PropertyMetadata(0));
They're most easily created using the propdp snippet in Visual Studio.
I recommend giving this MVA course a look (especially the first lesson) on how to create custom controls
I have created a user control in WPF, and in the code behind I have created some dependency properties.
I added several WPF controls to my user control, one of the is a progress bar, so What I tried to do is to expose the Value progressBar property as below:
public static readonly DependencyProperty valueProperty = DependencyProperty.Register(
"Value",
typeof(Double),
typeof(MyUserControl),
new FrameworkPropertyMetadata(
ValuePropertyCallback));
private static void ValuePropertyCallback(DependencyObject controlInstance, DependencyPropertyChangedEventArgs args)
{
MyUserControl myUserControlInstance = (ProgressControl)controlInstance;
myUserControlInstance.progressBar.Value = (Double)args.NewValue;
}
public Double Value
{
get { return (Double)GetValue(valueProperty); }
set { SetValue(valueProperty, value); }
}
And in XAML I have written this:
<MyUserControl Name="myControl" Value="{Binding ProgressBarValue}" >
But It seems not to be working, neither setting nor getting the value.
I have a couple hours reviewing this but I cant realize what I am doing wrong.
Hope you can help me, Thank you in advance.
(Note: DataContext are defined previously and it is correct since this is the only binding that does not work)
valueProperty <----> "Value" does not match... (v/V) :=)
Have you tried Mode=TwoWay:
<MyUserControl Name="myControl" Value="{Binding ProgressBarValue, Mode=TwoWay}" >
I have also used PropertyMetadata instead of FrameworkPropertyMetadata
Try changing the name of your dependency property to be PascalCased:
ValueProperty
You might also want to look at BindsTwoWayByDefault to make sure changes to your DP are written to the source object.
Turns out that my problem was that I didnt implement the INotifyPropertyChanged interface, so, the changes I did were not showed. But since I am new at WPF using MVVM I didnt know that.
But you just need to create an ObservableObject, then your viewModel class has to inherit from it.
Here is an example to create the ObservableObject class and how to inherit from it.
Can someone help me with this question?) In My XAML I have Listbox element. I want to add my user property into it(in my case - ConnectorStyle)
My XAML code:
<ListBox ItemsSource="{Binding Nodes}" ItemsPanel="{StaticResource CanvasItemsPanelTemplate}"
ItemTemplate="{StaticResource NodePictureTemplate}"
ItemContainerStyle="{StaticResource CanvasItemStyle}"
ConnectorStyle="{StaticResource ConnectorLineStyle}"/>
In my Model I have prepared this property:
public partial class MainPage : UserControl
{
public static readonly DependencyProperty ConnectorStyleProperty = DependencyProperty.Register(
"ConnectorStyle", typeof(Style), typeof(NodePicture), null);
public MainPage()
{
InitializeComponent();
}
public Style ConnectorStyle
{
get { return (Style)GetValue(ConnectorStyleProperty); }
set { SetValue(ConnectorStyleProperty, value); }
}
}
But I is a mistake - Cannot resolve ConnectorStyle.
Is there a simple (or a right way ) way of doing this?
There are two ways to do this: Either you can write a subclass for the ListBox that adds the DependencyProperty or you can write an attached property.
In your case you probably want to write a subclass that adds the property. Try something like this:
public class MyListBox : ListBox
{
public static readonly DependencyProperty ConnectorStyleProperty = DependencyProperty.Register(
"ConnectorStyle", typeof(Style), typeof(MyListBox), null);
public Style ConnectorStyle
{
get { return (Style)GetValue(ConnectorStyleProperty); }
set { SetValue(ConnectorStyleProperty, value); }
}
}
This will add a new type of ListBox that you can add in your xaml code. It will have all the same properties as a regular ListBox, but it will also have the ConnectorStyle property.
If you need to respond to changes to the ConnectorStyle property in your listbox then you should change the code for the Dependency Property, but that is outside the scope of this question.
And in XAML it shoul be :
<local:ListBoxEx
ConnectorStyle="{StaticResource ConnectorLineStyle}"/>