I have a UserControl that needs to be bind with two DataContext on the basis of a checkbox.
This UserControl have to display the data about the application (global) or selected DataGridRow.
class Person
{
public string Name {get; set;}
public string Age {get; set;}
}
UserControl has only two text fields to display name and Age. If "Global" checkbox is checked, then I want to bind this usercontrol with the property of APerson (of Person class) in MainViewModel and if it is unchecked then I have to bind the UserControl with the SelectedItem in DataGrid. SelectedItem is also a Person type
Basically you could just play with your ViewModel to get what you want. Here is one way to do it.
You would be binding the Checkbox.IsChecked to 'IsGlobal' property in the ViewModel.
Then you would be binding the userControl to another property, say SomePerson in the ViewModel.
Lastly, in the setter of IsGlobal you would change the SomePerson to either APerson or SelectedItem in your datagrid depending on the boolean state of IsGlobal.
[Adding this here since you want a way to do it purely in XAML. I think that insisting on pure XAML here is not essential and #bit's answer is the right way to go, IMO.]
You can use style to have triggers that do the change.
Let's say your UC is called MyUC and currently you have an instance of it similar to: <local:MyUC/> in some other view/UC/window. You can change the instance to look like so:
<local:MyUC>
<local:MyUC.Style>
<Style TargetType="{x:Type local:MyUC}">
<Setter Property="DataContext" Value="{Binding SelectedItem, ElementName=MyDataGrid}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyCheckbox, Path=IsChecked}"
Value="True">
<Setter Property="DataContext" Value="{Binding APerson}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</local:MyUC.Style>
</local:MyUC>
I'm changing here the data context property, but you can change any other dependency property on MyUC.
Again, I think this is a less favorite approach to tackle this functionality, but it's pure XAML.
Related
I have a function in my UI where I want to be able to collapse/make visible a text message depending on the value of a custom property in my window object.
Using online references, I have come up with this code-behind to register the property:
public bool ValidInterval
{
get { return pValidInterval; }
}
private bool pValidInterval = true;
public static readonly DependencyProperty ValidIntervalProperty = DependencyProperty.Register("ValidInterval", typeof(bool), typeof(Settings), new UIPropertyMetadata(true));
And this corresponding XAML for the label:
<Label Name="DynamicWarning" Content="Time interval must be a valid positive integer.">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding ValidInterval}" Value="true">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding ValidInterval}" Value="false">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Unfortunately, this does not work. I can get it to set the parameter depending on the initial value of the property, but doesn't update the visibility dynamically like I want. I have been looking at this for an hour and what I have seems consistent with examples I am finding online for similar operations. Am I doing something wrong, or can you not update the visibility on the fly? If the latter, how do I achieve an equivalent effect?
ΩmegaMan's answer is correct. But I wanted to clarify, you don't need a backing field with a dependency property, the static dependency property IS the backing field.
public bool ValidInterval
{
get { return (bool)GetValue(ValidIntervalProperty); }
set { SetValue(ValidIntervalProperty, value); }
}
However, if you aren't in need of a dependency object specifically, then you may just want to use INotifyPropertyChanged as ΩmegaMan has it right. Dependency properties are typically used when you need to bind another property to them, such as when making your own custom control. For example Visibility itself is the dependency property in your example and ValidInterval just needs to be a normal property that invokes the NotifyPropertyChanged event.
You need for the holder class of the properties which are bound to the page, to adhere to INotifyPropertyChanged Interface and implement it.
That process informs the bound controls on the page that something has changed, and when it has changed, then the control is "notified" of the change; then it reads afresh the property it is bound to.
For WPF/Xaml they specify the seperation of data concerns for the views to business logic, is done by implementing the Model-View-ViewModel or MVVM pattern.
The link provided is dry, and there are other resources which can describe on the net, but it simply says put all your business logic that is bound from the View to a separate View Model Class; which is instantiated on your View.
I provide a basic example, any version of .Net can be used, on my blog:
MVVM Example for Easier Binding
I have a number of radio buttons which are used to change an option, by being bound to a command with a command parameter, like this:
<RadioButton
Content="Option1"
Command="{Binding ChangeOption}
CommandParameter="Option1" />
The code to change options is the view model is quite simple:
public property SelectedOption { get; set; }
public void ChangeOption(string option)
{
SelectedOption = option;
}
This is simplified a bit, but it pretty much describes the concept. What I am missing is, to decide whether or not a radio button is checked, based on the SelectedOption property. I want to compare this property to the Content (or CommandParameter) of the RadioButton. This should be done in a trigger, which can then alter the IsSelected property.
The problem is, that I cannot figure out, how to access either the Content or CommandParamater in the Data Trigger. I am stuck at something like this:
<Style.Triggers>
<DataTrigger Binding={Binding SelectedOption} Value="?????">
<Setter Property="IsChecked" Value="True" />
</DataTrigger>
</Style.Triggers>
What do I put in the Value parameter of the Data Trigger, to compare it to the selected option?
This approach may cause you more headache than it's worth.
I would recommend creating a new class for these radio buttons:
public class OptionSelection
{
public bool IsSelected {get; set;}
public string Option {get; set;}
}
You can then create an ObservableCollection or List of these items and display them with an ItemsControl, binding to Option (with a Label or TextBlock) and IsSelected (with your RadioButton).
It's important to also implement INotifyPropertyChanged in this object so that the XAML bindings update accordingly.
I've got a style setter in a themes xaml file. I'm trying to bind the value of the Setter to a bool peoperty in a view model.
I've got the namespace to the view model in themes:
xmlns:propertyGrid="clr-namespace:MY.App.Controls.PropertyGrid;assembly=MY.APP.Controls"
and the binding in the style:
<Setter Property="IsExpanded" Value="{Binding Source={StaticResource propertyGrid:PropertyGridViewModel}, Path=AreCategoriesAutoExpanded}"/>
Finally in the viewmodel I just have an auto property:
public bool AreCategoriesAutoExpanded { get; set; }
However I get an exception at run time:
Cannot find resource named 'propertyGrid:PropertyGridViewModel'. Resource names are case sensitive
If I try to use a dynamic resource resource it compains that I can only bind to a dp. What is wrong with this binding? Is there something I'm missing?
This will only work if your ViewModel is a static class with a static property, like this:
<Setter Property="IsExpanded" Value="{Binding Source={x:Static propertyGrid:PropertyGridViewModel.AreCategoriesAutoExpanded}"/>
You were missing the 'x:Static' bit, which should fix it.
when I remove an item that is currently selected from the TreeView automatically the parent gets selected. I would like to change this behavior so the previous or the next child gets selected. I really don't know where to start ...
Any idea on how to accomplish this would be great!
Thanks.
You can set the SelectedItem by introducing a property such as IsSelected in your tree view node's datacontext class or model.
Assuming that you are binding a hierarchy of TreeViewItemModel class to the TreeView, you need to do the following
Add writeable IsSelected propertyb in TreeViewItemModel. Remember to raise property changed notification in the Setter of IsSelected.
Introduce this in the TreeView resources ...
<TreeView.Resources>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>
</TreeView.Resources>
After you delete a node, set the next or previous tree view child's TreeViewItemModel objects IsSelected as true.
Let me know if this helps.
TreeView has Items property, which is of type ItemCollection. This type has some good events, like CollectionChanged or CurrentChanged. may be you should to spade this way?
WPF application, .NET 3.5.
I have a ListView control, to which I bind a collection of business classes.
I'd like to bind the ForeColor of items to a bool property of the class (say: MyClass.Active), so that the items are displayed in black when active, in light gray when disabled.
I want listview items to change their color on-the-fly, I mean when I'd change Active value of one of the instances in my databound collection, its respective listview item would change its color automatically.
What do I need to achieve this? I've found numerous tutorials on WPF databinding on the net, some questions on StackOverflow, but not exactly the same thing, and I don't want to start combining my solution out of everything I can put my hands on, by trial and error.
I know about INotifyPropertyChanged (for my business class), IValueConverter (but should I need it for a bool??), DataTrigger etc.
But which pieces of the puzzle do I really need, what is the simpliest way to achieve my goal?
I would just do it in a style, and apply that style on your List items. Providing that your object implements INotifyPropertyChanged and the property changed event gets raised when IsActive changes, this will change the foreground to Gray if IsActive = False
<Style x:Key="DisableInactiveTextStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="False">
<Setter Property="Foreground" Value="LightGray" />
</DataTrigger>
</Style.Trigger>
</Style>
<TextBlock Style="{StaticResource DisableInactiveTextStyle}" ... />
I would suggest creating an IValueConverter that takes a bool and returns a color. You can then bind the ForeColor to the MyClass.Active property and use the created converter.