I have a WPF control (ControlA) which references another control (ControlB) like so:
<Grid>
<controls:ControlB x:Name="ControlB" />
<my:DataGrid
x:Name="dataGridBackup"
ItemsSource="{Binding}"
AutoGenerateColumns="False" >
<my:DataGrid.Columns>
<my:DataGridCheckBoxColumn
Header="Connectable"
Binding="{Binding Connectable}" />
</my:DataGrid.Columns>
</my:DataGrid>
</Grid>
Now in ControlB I have a button and i want to bind the IsEnabled property to the Connectable column of my Grid on controlA.
I can get it working when i have the controls on the same page but not in the aboce scenario. I tried with
<Button
IsEnabled="{Binding ElementName=dataGridBackup, Path=SelectedItem.Connectable}">
</Button>
Button inside ControlB has no normal way to know what's outside the control ControlB. One possible solution is to add boolean dependency property to ControlB like IsConnectable. In XAML of control ControlA, bind the property to dataGridBackup with path, like you did. In XAML of control ControlB, bind the button's IsEnabled property to IsConnectable of ControlB.
Related
I have the following CollectionViewSource in the main window and a custom control that utilizes that source:
<CollectionViewSource x:Key="cl1List" Source="{Binding Path=ResAmountMap}" Filter="OnCl1Filter"/>
//....
<control:ResAmounListView ResAmountMap="{Binding Source={StaticResource cl1List}}" />
The custom control is using ListView:
<ListView ItemsSource="{Binding Path=ResAmountMap}">
<ListView.View>
<GridView>
<GridViewColumn Header="Resource" DisplayMemberBinding="{Binding Path=Key}" />
</GridView>
</ListView.View>
</ListView>
The thing is that the ListView in custom control displays all elements from the source, but I expect it will display filtered ones.
When I used ListView directly in the main window (without custom control) then it displayed filtered only items.
Any ideas why filtering stops working when CollectionViewSource is passed to custom control?
Assuming that you have (correctly!) not explicitly set the control's DataContext property, the expression
ItemsSource="{Binding Path=ResAmountMap}"
binds directly to the inherited DataContext, and hence directly to the source property in the view model (which accidentially has the same name as the control property).
In other words, the ListView in your control does not use the control property at all.
Write the binding like shown below, and in case it is not a UserControl, replace UserControl by the actual base class of your control.
ItemsSource="{Binding Path=ResAmountMap,
RelativeSource={RelativeSource AncestorType=UserControl}}"
I am building a simple application that mainly consists of a TabControl and a StatusBar with an Slider. Each tab hosts an custom control that can be zoomed in & out. The slider in the status bar should give the user the abillity to zoom in & out the content of the currently selected tab. My problem is that I'am unable to assign the sliders value to the currently selected custom control.
Here's the xaml of my TabControl:
<TabControl x:Name="MyTabControl" ItemsSource="{Binding MyItems}">
<TabControl.ContentTemplate>
<DataTemplate>
<controls:MyControl x:Name="foo" DataContext="{Binding}">
</controls:MyControl>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
For the slider I want something like this, but it should be bound to the "foo.bar" property of the currently selected tab:
<Slider
Value="{Binding ElementName=foo, Path=bar}">
</Slider>
Is that possible or is there a better way to use a Slider to adjust and display a property of the currently selected custom control?
You can try adding a Value property to the class (or classes) that are set as the DataContext for each TabItem. Then you could data bind the Slider.Value property to the Value property in the data item from the selected TabItem using the TabControl.SelectedItem property. Try this:
<Slider Value="{Binding Path=SelectedItem.Value, ElementName=MyTabControl}" />
Background:
I have a ListBox containing items defined by DataTemplates. Right now, if an object in the list has the property IsEditable set to true, the item's property information will be displayed inside of textboxes (via DataTemplate change), instead of textblocks (so the user can edit the content of that list item)
IsEditable is toggled on/off by a button inside of each list item. I have been told that we need to keep the state of all objects consistent, which means I can't just rebind the ItemsSource and lose everything.
Currently, I'm using this to re-render:
this.lbPoints.Dispatcher.Invoke(DispatcherPriority.Render, new Action(() => { }));
Question:
The aforementioned code snippet KIND OF does its job. By "kind of", I mean, it does eventually cause my data to become re-rendered, but only when I scroll to the bottom of the list and then scroll back up to the item i'm trying to re-render.
1) How can I re-render the data immediately without having to scroll around to get it to show up?
The guys commenting are right that you're going about this the wrong way... there is rarely a need to force a ListBox to re-render. You're probably causing yourself some additional grief trying to switch the DataTemplates (although it is possible). Instead of that, think about data binding the TextBox.IsReadOnly property to your IsEditable property:
<TextBox IsReadOnly="{Binding IsEditable}" Text="{Binding Text}" />
Another alternative is to use a BooleanToVisibilityConverter to show a different Grid in your DataTemplate when your IsEditable property is true. Unfortunately, that Converter doesn't have an inverse operation, so you could create an IsNotEditing property to bind to the Grid in the DataTemplate that is originally displayed. I'm not sure if that's clear... see this example:
<DataTemplate DataType="{x:Type YourPrefix:YourDataType}">
<Grid>
<Grid Visibility="{Binding IsNotEditing, Converter={StaticResource
BooleanToVisibilityConverter}}">
<!-- Define your uneditable UI here -->
</Grid>
<Grid Visibility="{Binding IsEditing, Converter={StaticResource
BooleanToVisibilityConverter}}">
<!-- Define your editable UI here -->
</Grid>
</Grid>
</DataTemplate>
You could also define your own BooleanToVisibilityConverter class that has an IsInverted property, so that you can just use the one IsEditing property. You'd need to declare two Converters still, like this:
<Converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter" />
<Converters:BoolToVisibilityConverter x:Key="InvertedBoolToVisibilityConverter"
IsInverted="True" />
Then your XAML would be like this:
<Grid Visibility="{Binding IsEditing, Converter={StaticResource
InvertedBoolToVisibilityConverter}}">
<!-- Define your uneditable UI here -->
</Grid>
<Grid Visibility="{Binding IsEditing, Converter={StaticResource
BoolToVisibilityConverter}}">
<!-- Define your editable UI here -->
</Grid>
I'm trying to bind element's property in a child control to an element's property ina parent window, it doesn't work..
Here is png of what I'm trying to do:
Here is the xaml that doesn't work:
CurrentDate="{Binding ElementName=TimeBar, Path=SelectionStart,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"
Thanks.
create a dependency property in your usercontrol and then bind to it in your window
something like that: DependencyProperty implementations you can find all around here on stackoverflow
<YourUsercontrol x:Name="uc">
<YourSomeControl CurrentDate="{Binding ElementName=uc, Path=MyDp}"/>
</YourUsercontrol>
xaml window
<Window>
<ElementInParent x:Name="eip" />
<YourUsercontrol MyDp="{Binding ElementName=eip, Path=PropertyFromElementInParent}"/>
based on the following Answer LINK the SelectionStart is not a Bindable Probperty by default so you need to create a attached behavior or something similar
Binding ElementName along with Relative Source is not correct approach.
Besides the UserControl does not know the ElementName of the Parent since the two are in different XAML.
One approach is to set the data context of user control with the element name you want to bind it to and then use normal binding Path.
As shown in the example below:
In main window, we have a textbox and a user control.
We are setting data context of the user control with the text box.
In the user control, we are binding the Text property of the DataContext (which is essentially TextBox of main window).
<Window
xmlns:self="clr-namespace:experiments"
>
<StackPanel>
<TextBox x:Name="Name" Width="100"/>
<self:UserControl1 DataContext="{Binding ElementName=Name}"/>
</StackPanel>
</Window>
<UserControl x:Class="experiments.UserControl1">
<Grid>
<TextBlock Text="{Binding Path=Text}" Width="100" Background="AliceBlue" Height="50"/>
</Grid>
</UserControl>
I developed a user control in SilverLight that contains several child controls. Textboxes, ComboBoxes and so on.
The problem is, when I include that UserControl into a parent view and set the complete control to IsEnabled=False, the child controls in that specific UserControl are still enabled.
After all I found the problem.
Adding something like that, implies that the IsEnabled Binding is located in the UserControl binding, not as expected from myself in the DataContext of the parent.
<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
IsEnabled="{Binding CanModify}" DataContext="{Binding Confidentiality}"/>
QUESTION:
But there's still the question how I can bind the IsEnabled to the ViewModel of the Parent? Because it's not very elegant to copy the CanModify Property to the ViewModel of the Child Control.
Instead of modifying a binding in some way (for example you can make it dependent on other control name as it is proposed in other answer) I would move separate the control which will be disabled and control where DataContext will be changed. For example:
<ContentControl IsEnabled="{Binding CanModify}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<localControls:TeamEmployeeSelector DataContext="{Binding Confidentiality}"/>
</ContentControl>
Here is how I would do this.
Your TeamEmployeeSelector UserControl will contain a single root level element which by default is a Grid and is given the name "LayoutRoot".
Now you can bind the IsEnabled property of all the child elements to the UserControl like this:-
<TextBox IsEnabled="{Binding Parent.IsEnabled, ElementName=LayoutRoot}" ... />
By using element-to-element binding you do not need to copy the CanModify property in to child view models.
Some might suggest that you simply add an x:Name to your UserControl element and then bind directly to it rather than going via the Parent property of the root element as I do above. That'll work ok in Silverlight 4 but not in 3 or WP7. Personally I prefer the above.
This is a scoping issue. Generally, when creating a UserControl, you want to set itself as the DataContext for its sub-elements. This is most easily accomplished in the constructor:
UserControlExample() {
InitializeComponent();
RootElement.DataContext = this;
}
Where RootElement is the name you give to this first child (usually a Grid or panel) of your UserControl.
From here you can set natural bindings for your sub-elements like so:
<TextBox x:Name="MainTextBox" IsEnabled={Binding IsEnabled} />
This works, since TextBox inherits the DataContext of the parent layout panel.
Finally, if you want to have your UserControl's IsEnabled property to be related to its parent, this is best done at the point of declaration:
<Grid>
<UserControlExample IsEnabled={Binding CanModify} />
</Grid>
This way you keep your concerns separate. The sub-controls don't care what the UserControl is reflecting. They just need to know how to enable/disable when the control's IsEnabled property flips.
sub-controls IsEnabled bound to --> (UserControlExample is DataContext)
UserControlExample.IsEnabled bound to --> (VM is DataContext)
VM.CanModify
I don't know if it's possible in Silverlight, but in WPF I would use RelativeSource.
Have a look here.
Hope this help !
<localControls:TeamEmployeeSelector Grid.Row="1" Grid.Column="0"
Grid.ColumnSpan="2" IsEnabled="{Binding ElementName=SomeElementName_With_Parent_ViewModel, Path=DataContext.CanModify}" DataContext="{Binding Confidentiality}"/>