So here I come creating a user control. It consists of a treeview dropping down from a combobox.
Actually, there is a button with a control (DropTree) dropping down from its contextmenu. So I have a control DropTree.
public partial class DropTree : UserControl
{
public TreeView TreeView
{ get{return treeView;} }
public DropTree()
{ InitializeComponent(); }
}
to simplify it, I made the TreeView control public, then I have my main control which is called ComboTreeView.
Now I need to represent some treeview properties in it, so I define several dependency properties:
public static DependencyProperty SelectedItemProperty = DependencyProperty.Register("SelectedItem", typeof(object), typeof(ComboTreeView), new FrameworkPropertyMetadata { Inherits = true, IsNotDataBindable = false, DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}
and in constructor it is:
public ComboTreeView()
{
InitializeComponent();
TreeViewControl.SetBinding(TreeView.SelectedItemProperty, new Binding("SelectedItem") { Source = this, Mode = BindingMode.TwoWay });
}
and it all seems ok, until i run it. It crashes saying that SelectedItem cannot be binded to data. I don't understand?
The same goes for ItemsSource and SelectedValue... but only SelectedValuePath property defined this way goes fine.
Can anybody help? Or is there any other way to bind it correctly?
PS: by the way, I need to use DataBinding for ComboTreeView in my code later.
Try to set the Binding on SelectedValue instead of SelectedItem.
TreeView.SelectedItem is a readonly property. You can't set it, whether explicitly or through binding. In order to select a node in a TreeView, you must set the TreeViewItem.IsSelected property to true.
Related
I've got a UserControl with a DependencyProperty created in its CodeBehind:
public partial class PanelMap_Control : UserControl
{
public ObservableCollection<GMapMarker> Markers
{
get { return (ObservableCollection<GMapMarker>)GetValue(MarkersProperty); }
set { SetValue(MarkersProperty, value); }
}
public static readonly DependencyProperty MarkersProperty = DependencyProperty.Register("Markers", typeof(ObservableCollection<GMapMarker>), typeof(PanelMap_Control), new PropertyMetadata(null));
}
Inside the UserControl is a Map, which contains the original collection of markers (not a DependencyProperty). I need to make this available for binding outside the UserControl, so at the end of the constructor (once the map's Markers are all setup), I set it to the control's DependencyProperty:
public PanelMap_Control()
{
InitializeComponent();
//...map setup...
this.Markers = _map.Markers;
}
Then, users of the UserControl can bind like:
<local:PanelMap_Control Markers="{Binding Path=MapMarkers, Mode=OneWayToSource}"/>
Where in the ViewModel:
public ObservableCollection<GMap.NET.WindowsPresentation.GMapMarker> MapMarkers
{
private get
{
return _mapMarkers;
}
set
{
_mapMarkers = value;
}
}
private ObservableCollection<GMap.NET.WindowsPresentation.GMapMarker> _mapMarkers;
The problem is, the ViewModel's MapMarkers property always ends up with the default value "null." I tried setting breakpoints on the SetValue call in PanelMap_Control and the ViewModel property's setter. The debugger first hits SetValue(), at which point _map.Markers is valid (non-null). THEN it hits the ViewModel's setter, with a value of null - and never reflects the actual valid object I pass to SetValue().
I'm sure I'm just missing something simple, but I can't for the life of me figure out why SetValue(non-null) would be followed by ViewModel.MapMarkers.set(null)...and never again.
(Side note 1: I realize this DependencyProperty won't work for TwoWay binding - i.e. I can't update _map.Markers in the UserControl. That's fine, I only need to read from it externally.)
(Side note 2: The _map.Markers object will never be changed - only the items in the collection - so setting the DependencyProperty to the initial collection should be sufficient.)
Please refer to the following questions.
OneWayToSource Binding seems broken in .NET 4.0
OneWayToSource binding resetting target value
OneWayToSource does actually reset the target property (Markers) initially. This is by design. There is more information about this on the links above.
As a workaround you could try to set up the binding programmatically:
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
DataContext = vm;
vm.MapMarkers = control.Markers;
BindingOperations.SetBinding(control, PanelMap_Control.MarkersProperty, new Binding("MapMarkets") { TargetNullValue = control.Markers, FallbackValue = control.Markers });
}
XAML:
<local:PanelMap_Control x:Name="control" />
My boss had downloaded a xaml control that I must use in app. It looks like ok but there is a strange trouble with inner logic - the
property CurrentColor (that I need to use in our app) is defined in control.xaml.cs file like :
public SolidColorBrush CurrentColor
{
get { return (SolidColorBrush)GetValue(CurrentColorProperty); }
set
{
SetValue(CurrentColorProperty, value);
ActiveColor = CurrentColor;
}
}
I am using this control in my dialog (that has its own view model class) and
I am writing this kind of binding:
CurrentColor="{Binding myOwnViewModel.ColorActualValue, Mode=Default, UpdateSourceTrigger=PropertyChanged}">
in myOwnViewModel.cs (that implements INotifyPropertyChanged) I have my property
public SolidColorBrush ColorActualValue{ // here is some logic}
But when I debug an app I have never target MY CurrentColor - I am always go to the CurrentColor from control.xaml.cs
How could I bind this "third party" control to my property from my ViewModel?
Perhaps this is because (control.xaml.cs):
public static DependencyProperty CurrentColorProperty =
DependencyProperty.Register("CurrentColor", typeof(SolidColorBrush), typeof(ColorPickerComboBox), new PropertyMetadata(Brushes.Chocolate));
public static RoutedEvent ActiveColorChangedEvent = EventManager.RegisterRoutedEvent("ActiveColorChanged",
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ColorPickerComboBox));
I have found the question What's wrong with "DataContext = this" in WPF user controls? and removed DataContext = this; from constructor of this control - but this still not helped
Should the binding look like this?
CurrentColor="{Binding ColorActualValue, Mode=Default, UpdateSourceTrigger=PropertyChanged}">
The DataContext of your 'dialog' needs to be the ViewModel class that contains the ColorActualValue property
public Dialog()
{
DataContext = new myOwnViewModel();
}
I am new to binding. I have binded slider value to my control's property and my controls property get changed when I change the slider value.
Now, when I need to change the slider value by changing my property value, it does not work..
I modified the xaml from some internet source, but still not get the expected output.
can anyone help me out...
<Grid>
<cc:MyControl Name="mycntrl" ZoomPercentage="{Binding ElementName=slider,Path=Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></cc:MyControl>
<Slider Name="slider" Margin="20,20,20,400" Minimum="100" Maximum="400"></Slider>
</Grid>
Updated:
My code behind for my ZoomPercentage dependency property is below
public double ZoomPercentage
{
get
{
return (double)GetValue(ZoomPercentageProperty);
}
set
{
SetValue(ZoomPercentageProperty, value);
}
}
My dependency registration
public static readonly DependencyProperty ZoomPercentageProperty = DependencyProperty.Register("ZoomPercentage", typeof(double), typeof(MyControl), new FrameworkPropertyMetadata(ZoomPercentagePropertyChanged));
public static void ZoomPercentagePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
if (args.OldValue != null)
{
if ((double)args.NewValue != (double)args.OldValue)
{
MyControl mycontrol = obj as MyControl;
mycontrol .ZoomTo((int)((double)args.NewValue));
}
}
}
Your ZoomPercentage property should be implemented as a Dependencyproperty
Something like this
public class MyControl:UserControl
{
public MyControl() : base() { }
public double ZoomPercentage
{
get { return (double)this.GetValue(ZoomPercentageProperty); }
set { this.SetValue(ZoomPercentageProperty, value); }
}
public static readonly DependencyProperty ZoomPercentageProperty = DependencyProperty.Register(
"ZoomPercentage", typeof(double), typeof(MyControl:),new PropertyMetadata(0));
}
read more here
If you want a data bound control in the UI to update after changes made in code then you have to do one of two things. One option is to correctly implement the INotifyPropertyChanged interface in the class that you declared your Value property.
The other is to declare your Value property as a DependencyProperty, although you should only really do this in the code behind of your Window or UserControl and opt for the first method if you are using a view model. The purpose of these two methods is for you to 'plug in' to WPF notification framework, so that your UI control will update. Please read the linked pages for more information.
I created a custom controll in expression Blend and added a property. I found the property in Blend, but the option for create a databinding isn't available. What do I have to make that I can add databindings through Blend?
Code Property:
public string TileText
{
get { return this.labelTileText.Text; }
set { this.labelTileText.Text = value; }
}
If you want to enable databinding on a property of a custom control, you need to create a dependency property for that property.
The property:
public string TileText {
get { return this.labelTileText.Text; }
set { this.labelTileText.Text = value; }
}
Dependency property:
public static readonly DependencyProperty TileTextProperty = DependencyProperty.Register(
"TileText", typeof(String), typeof(ClassName), new UIPropertyMetadata("default value", callBack));
And then you should implement that callBack function that to be called whenever 'TileText' property is changed.
I've created a silverlight UserControl with some inner elements that I'd like to custom change when the controls isEnabled property is set (for example changing some inner Image controls to look greyed out). With other properties I set up a DependencyProperty and do the code there, but this doesn't called for isEnabled (I assume because it's already declared). The code is below;
public static readonly DependencyProperty EnabledProperty =
DependencyProperty.Register("isEnabled", typeof(bool), typeof(BreadcrumbElement), null);
public bool isEnabled
{
get { return (bool)GetValue(TitleProperty); }
set
{
SetValue(TitleProperty, value);
if (value)
Chevron.Source = new BitmapImage(new Uri("../Resources/ChevronRight.png", UriKind.Relative));
else
Chevron.Source = new BitmapImage(new Uri("../Resources/ChevronRight_Disabled.png", UriKind.Relative));
}
}
I'd like to use isEnabled instead of something else, so is there a way to get this to function correctly? Thanks :)
Hook onto Control.IsEnabledChanged Event and write your code in the handler of this event
http://msdn.microsoft.com/en-us/library/system.windows.controls.control.isenabledchanged%28v=vs.95%29.aspx