I've seen on the internet quite a few examples of binding a boolean to the Visibility property of a control in XAML. Most of the good examples use a BooleanToVisibiliy converter.
I'd like to just set the Visible property on the control to bind to a System.Windows.Visibility property in the code-behind, but it doesn't seem to want to work.
This is my XAML:
<Grid x:Name="actions" Visibility="{Binding Path=ActionsVisible, UpdateSourceTrigger=PropertyChanged}" />
This is the code for the property:
private Visibility _actionsVisible;
public Visibility ActionsVisible
{
get
{
return _actionsVisible;
}
set
{
_actionsVisible = value;
}
}
In the constructor of the Window, I also have this call:
base.DataContext = this;
When I update either ActionsVisible or this.actions.Visibility, the state doesn't transfer. Any ideas to what might be going wrong?
Change your property to be a DependencyProperty. This will handle the updating for you.
public Visibility ActionsVisible
{
get { return (Visibility)GetValue(ActionsVisibleProperty); }
set { SetValue(ActionsVisibleProperty, value); }
}
// Using a DependencyProperty as the backing store for ActionsVisible. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ActionsVisibleProperty =
DependencyProperty.Register("ActionsVisible", typeof(Visibility), typeof(FooForm));
I think the problem is that WPF can't know that your ActionsVisible property has changed since you've not notified the fact.
Your class will need to implement INotifyPropertyChanged, then in your set method for ActionsVisible you'll need to fire the PropertyChanged event with ActionsVisible as the property name that has changed.
Hope this helps...
Write: NotifyPropertyChanged("ActionsVisible")
Related
I created a custom renderer for a Label. Now I wanted to manipulate with its focus state, so I created bindable property and event. It works fine when I change the bindable property from custom renderer like so: Element.IsFocused = true;
But when I change it from the view model, it affects XAML view, but for some reasons doesn't call the setter for this property. Here is the code:
In custom class:
public new static readonly BindableProperty IsFocusedProperty =
BindableProperty.Create(nameof(IsFocused), typeof(bool), typeof(FloatingEntry), false);
public new bool IsFocused
{
get { return (bool)GetValue(IsFocusedProperty); }
set
{
SetValue(IsFocusedProperty, value);
if (value) Focus();
}
}
In XAML:
IsFocused="{Binding PasswordEntryIsFocused}"
In View Model:
private bool _passwordEntryIsFocused;
public bool PasswordEntryIsFocused
{
get { return _passwordEntryIsFocused; }
set
{
SetProperty(ref _passwordEntryIsFocused, value);
}
}
In View Model in some method: PasswordEntryIsFocused = true;
It's not about new keyword, I tried without it.
And binding works, because I tried to bind it with a visual property, like IsVisible and it was working like it should, but setter is always called only from a custom renderer.
I think I may miss something in a context of bindable property work.
But when I change it from the view model, it affects XAML view, but for some reasons doesn't call the setter for this property.
Yes, that is a common mistake with WPF. The XAML generated code does not call the setter, instead it changes the bound dependency property immediately. You can't break on this event, unless you attach the PropertyChangedCallback event.
I have a list of objects (ObservableCollection subjectlist) and want to display them in a Combobox via data-binding and dependency property.
WPF Data Binding to a Combo Box
I searched on stackoverflow and tried to implement the solution of Craig Suchanec in the link above. (tried the whole day now and I just don't get what's wrong with my code)
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public static readonly DependencyProperty SubjectListProperty =
DependencyProperty.Register("SubjectList",
typeof(ObservableCollection<Subject>),
typeof(MainWindow));
private ObservableCollection<Subject> subjectList = new ObservableCollection<Subject>();
Initialization init1;
public ObservableCollection<Subject> SubjectList
{
get { return (ObservableCollection<Subject>)GetValue(SubjectListProperty); }
// get { return subjectList; }
}
public MainWindow()
{
init1 = new Initialization();
subjectList = init1.createMenuSubject();
InitializeComponent();
//this.comboBox.DataContext = SubjectList;
}
}
MainWindow.xaml
<Grid>
<ComboBox x:Name="comboBox" HorizontalAlignment="Left"VerticalAlignment="Top" Width="120" Margin="321,10,0,0"
ItemsSource="{Binding ElementName=mainWindow, Path=SubjectList}" DisplayMemberPath="Name"/>
</Grid>
It DOES work if I just set the DataContext and work without dependency property, but as soon as I try to use the dependency property for data-binding it does NOT and I don't see the significant difference between my implementation and the solution given in the link.
It would be much appreciated, if somebody could help me with this problem.
I can't see anywhere in your code where you are actually setting the value of the SubjectList property.
You are however setting the value of subjectList, but you're binding to SubjectList. Note the casing difference.
You should write:
public ObservableCollection<Subject> SubjectList
{
set { base.SetValue(SubjectListProperty, value); }
get { return (ObservableCollection<Subject>)base.GetValue(SubjectListProperty); }
}
instead of
public ObservableCollection<Subject> SubjectList
{
set { base.SetValue(SubjectListProperty, value); }
get { return subjectList; }
}
or any other ad hoc format. You are setting subjectList in your constructor MainWindow(), however, it will not set the value of SubjectList (with Capital S) and a property change event is never raised. Remove subjectList.
If you are wondering why the DataContext approach works, you should note it will work even if you do not use a DepenedencyProperty. However, if you implement INotifyPropertyChange, it will work with setting ElementName too.
App.cs
class customRadioButton:RadioButton
{
private Brush enableColor;
private Brush disableColor;
public EnableColor()
{
get{ /*get value */}
set{ /* set value */}
}
}
Main.xaml
<local:customRadioButton EnableColor={Binding ElementName=disableButton, Path=EnableColor} />
<local:customRadioButton x:Name="disableButton" EnableColor="Red", Path=EnableColor} />
Now I am changing the value of EnableColor dynamically. Problem I am having is that the value assigned but is not getting reflected in main.window
I don't want to use dependency property
Is there any other method to Tell the Binded Elements that its property has changed.
Note:I have tried UpdateTrigger its also not working
In order to get Binding work, you will need to create a DependencyProperty.
public Brush EnableColor
{
get { return (Brush)this.GetValue(EnableColorProperty); }
set { this.SetValue(EnableColorProperty, value); }
}
public static readonly DependencyProperty EnableColorProperty = DependencyProperty.Register(
"EnableColor", typeof(Brush), typeof(customRadioButton), new PropertyMetadata(default(Brush));
Read MSDN for details.
Curious what your aversion is to using a dependencyproperty? I answering this on my phone so cant mock one up for you but it would be extremely simple to do.
Just do a Google for "WPF custom control dependency property example" and do exactly what they do just customized for your needs.
The dependency peppery will give you the change notification that you're looking for.
The UpdateTrigger would only apply if you were binding to something that's part of your XAML data context. I mean I guess toy could fudge around to get that to work but DependencyProperty is absolutely the way too go
I'm puzzled by this probably trivial matter. I have my custom property on a descendant of DevExpresses class LayoutGroup (shouldn't make any difference IMO):
public class ExpandableLayoutGroup : LayoutGroup
{
public static readonly DependencyProperty IsExpandedProperty = DependencyProperty.Register("IsExpanded", typeof(Boolean), typeof(ExpandableLayoutGroup));
public Boolean IsExpanded
{
get { return (Boolean) GetValue(IsExpandedProperty); }
set
{
expandCheckBox.IsChecked = value;
SetValue(IsExpandedProperty, value);
}
}
}
Then I have XAML binding to a listbox (containing 2 items at this time) called listStates.
<ExpandableLayoutGroup x:Name="groupTool" IsExpanded="{Binding SelectedValue.IsTool, ElementName=listStates}" DataContext="{Binding Tool}" Header="Tool" View="GroupBox" />
The object list binding to listStates contains both properties (simplified):
public class State
{
public Boolean IsItemTool { get; private set; }
public Tool Tool { get; private set; }
}
Am I missing something obvious? Because I would expect that when I change listbox selection (single) it would also update IsExpanded property on a group. I have more subproperties of Tool binded (as apparent by DataContext="{Binding Tool}") and those update well. So the DataContext is changing correctly on listbox selection. Except this one property IsExpanded (that should expand/collapse layoutgroup).
What am I doing wrong, and how to make it so, that when listbox changes, IsExpanded binding is polled to get value from IsTool, and will set it (depending on selection).
Getters and setters of dependency properties must contain only GetValue and SetValue calls, because there're two ways to get and set their values: using getters and setters and using DependencyProperty or DependencyPropertyKey. This is why code in your setter is not executed (bindings don't use them for dependency properties). If you want some code to be executed when the value is changed, specify it as a PropertyChangedCallback callback in PropertyMetadata.
See PropertyChangedCallback Delegate on MSDN.
The setter for a dependency property must only set the value for it's underlying type. The .NET internals reserve the right to call SetValue() directly (and in my experience WPF usually does, while Silverlight uses the setter that you've defined).
Refer to the "Implications for Custom Dependency Properties" section of XAML Loading and Dependency Properties for details
I've created a UserControl which is essentially a button. It's got an Image and a Label on it and I've created two properties to set the Image's source and the Label's text like so:
public ImageSource Icon
{
get { return (ImageSource)this.GetValue(IconProperty); }
set { this.SetValue(IconProperty, value); icon.Source = value; }
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NavigationButton));
public string Text
{
get { return (string)this.GetValue(TextProperty); }
set { this.SetValue(TextProperty, value); label.Content = value; }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(NavigationButton));
However, when I've added the control to my Page, the controls wont respond to any properties I set in XAML, e.g. <controls:MusicButton Icon="/SuCo;component/Resources/settings.png/> does nothing.
What am I doing wrong?
CLR properties that wrap dependency properties should never have any logic other than calling GetValue and SetValue. That is because they may not even be called. For example, the XAML compiler will optimize by calling GetValue/SetValue directly rather than using your CLR property.
If you need to execute some logic when a dependency property is changed, use metadata:
public ImageSource Icon
{
get { return (ImageSource)this.GetValue(IconProperty); }
set { this.SetValue(IconProperty, value); }
}
public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(NavigationButton), new FrameworkPropertyMetadata(OnIconChanged));
private static void OnIconChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
//do whatever you want here - the first parameter is your DependencyObject
}
EDIT
In my first answer, I assumed your control's XAML (be it from a template or directly in a UserControl) is correctly hooked up to the properties. You haven't showed us that XAML, so it was perhaps an incorrect assumption. I'd expect to see something like:
<StackPanel>
<Image Source="{Binding Icon}"/>
<TextBlock Text="{Binding Text}"/>
</StackPanel>
And - importantly - your DataContext must be set to the control itself. You can do this in various different ways, but here is a very simple example of setting it from the code behind:
public YourControl()
{
InitializeComponent();
//bindings without an explicit source will look at their DataContext, which is this control
DataContext = this;
}
Have you tried setting the text property as well? The source of an image may just be wrong. Text is much more straight forward.
Also, in your example, you missed a quotation mark. So if it's copied from your real code, you may want to check that.
Barring those minor admittedly unlikely causes for your problem, I'd suggest setting the properties in code to check whether that has any effect. If it has, then you should really check your XAML.
Since you haven't posted the rest of your code, I can't really tell if you have problems somewhere else that might affect the control.
And yes, I know I'm not very helpful, but I've been working with WPF for only a little while. Hope it helps anyway.