I have an itemscontrol that is bound to a collection of objects.
in the data template, i bind an action that is to be used by all of the controls created if their focus is lost.
In the control, there is a textbox so if there are 1 items in the item controls ItemSource, there will be 2 textboxes.
Now, if Textbox 1 has focus and I click somewhere besides Textbox 2, the action is executed once (because the focus was lost). But if I click in Textbox 2, the action is executed twice. Why?
<ItemsControl Grid.Row="1" Margin="0,5,0,5" ItemsSource="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=Collection}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type ct:CollectionItem}">
<cc:TestControl
ValueChangedAction="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}, Path=ValueChangedAction}"
VerticalAlignment="Center" HorizontalAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
This is the Control.
<ewt:DecimalUpDown Tag="{Binding Uid}" Grid.Row="0" Grid.Column="3"
HorizontalAlignment="Stretch" TextAlignment="Left" Margin="10,5,10,5"
FormatString="C2" ShowButtonSpinner="False" VerticalAlignment="Center"
Value="{Binding Value}" LostFocus="DecimalUpDown_LostFocus" />
The bound action is executed in this event handler.
If your action is supposed to update the source of the binding (e.g. the Window, it looks like from your example), you might want to try adding OneWayToSource to your Binding so that binding only occurs one way—from the textbox to whatever it's bound to.
Related
I have an ItemsControl whose for the ItemTemplate DataTemplate contains a Button. I want the Command on the button to bind to a Command on the DataContext of the ItemsControl, not the ItemTemplate. I think the solution has to do with using RelativeSource, but my attempts so far have failed:
<ItemsControl ItemsSource="{Binding Games}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Command="{Binding Path=GameSelectedCommand, Source={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"
CommandParameter="{Binding}"
Style="{StaticResource MenuButtonStyle}"
Content="{Binding Name}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
How can I get the Button to bind to the GameSelectedCommand of the ItemsControl's DataContext object?
You're setting the source of the binding to the ItemsControl itself. Therefore, you'll need to dereference the DataContext of the ItemsControl:
Command="{Binding DataContext.GameSelectedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"
How would you have known this? Take a look at your debug output window when running the app. You'll see a message along the lines of "Cannot resolve property 'GameSelectedCommand' on type 'ItemsControl'".
I have a Page and a viewmodel is set as its datacontext. in that page I have a list. which is populating through a property in the viewmodel. List has a user control. and that user control has a button. I want that button to be bind with a command that is in viewmodel. Is there anyway to do that?
<Page DataContext=PageViewModel>
...
<ScrollViewer Grid.Row="3" Margin="20,0" Visibility="{Binding ByVenueSelected, Converter={StaticResource BooleanToVisibilityConverter}}">
<StackPanel>
<ItemsControl ItemsSource="{Binding EventsListByVenue}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<myControls:EventDetails /> <!--in this control i want to bind a command available in PageViewModel-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
...
</Page>
with help of #FunksMaName, I solved this. I am sure there are more elegant and better approach, but yet this is a quick & easy solution for me:
<Button Style="{StaticResource NoHighlightButtonStyle}" Tag="{Binding link}" CommandParameter="{Binding Path=Tag,RelativeSource={RelativeSource Mode=Self}}" Visibility="{Binding link,Converter={StaticResource DataAvailabilityToVisibilityConverter}}" Command="{Binding Path=Event.LinkCommand,Source={StaticResource Locator}}" >
<TextBlock Margin="0,5" Foreground="SkyBlue" Text="{Binding link}" TextWrapping="Wrap" FontSize="16"/>
</Button>
things to note:
i think xaml searched the command parameter in context of command only, so it was giving me null parameter, while the same binding was working fine for textblock inside Button. So i tricked it to store the value in tag, and used it from there.
Tag="{Binding link}" CommandParameter="{Binding Path=Tag,RelativeSource={RelativeSource Mode=Self}}"
I have a problem with extended selection in ListBox. Let's say I have a ListBox with 10 items and I'm selecting first 5 of them using Shift button. The SelectionChanged event is fired with 5 items. After that I want to select 3 items from those 5, again with Shift button pressed, but SelectionChanged event is not fired. How can I react to the second selection of items, when I'm selecting 3 of those 5 previously selected ones?
can you show the xaml code as well I would like to see what your binding looks like
it should looks something like this.. but I can't be certain unless I see your code
In Command binding you have used binding which has relative source binding...
consider making these changes in binding
1) using list box as Ancestortype
2) While binding use Path=DataContext.SelectionChangedCommand otherwise it will take list box as datacontext.
<catel:EventToCommand Command="{Binding Path=DataContext.SelectionChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True" />
here is an example of what the XAML would look like for ListBoxItem Template
<Grid>
<StackPanel Orientation="Horizontal">
<Label Width="180">Field1</Label>
<ListBox Height="200"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding List1, Mode=OneWay}"
Name="listBox1"
SelectionMode="Single"
Width="300">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="290">
<TextBlock Width="90" Text="{Binding}"></TextBlock>
<ComboBox Width="180" ItemsSource="{Binding DataContext.List2, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" DisplayMemberPath="Field1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<catel:EventToCommand Command="{Binding Path=DataContext.SelectionChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
I'm using .Net 4.0 and have a DataGrid in a view. I have implemeneted this http://www.codeproject.com/Articles/42227/Automatic-WPF-Toolkit-DataGrid-Filtering to provide filtering. The ItemsSource for the DataGrid is an observable collection of my custom objects.
Each row has a Button that when clicked, passes the selected custom object back via the CommandParameter.
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding Path=DataContext.DeleteMyCustomObjectCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}" CommandParameter="{Binding}" Width="20">
<Image Source="/MyThing;component/Images/delete.png" Height="16" Width="16"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
I want to be able to save the filter criteria using this solution http://www.codeproject.com/Articles/42227/Automatic-WPF-Toolkit-DataGrid-Filtering?msg=3342202#xx3342202xx but one of the calls requires a reference to the data grid
QueryController queryController= DataGridExtensions.GetDataGridFilterQueryController(myGrid1);
As i'm using MVVM, I don't have a reference to the DataGrid in my ViewModel. My command execution code (in the ViewModel) looks like this at present
public void DeleteMyCustomObject(object param)
{
MyCustomObject m = param as MyCustomObject;
.....Deletion commands go here
Is there a way I can use multibindings on the CommandParameter of my Delete button to pass back the custom object from the current row, and a reference to the actual DataGrid (or is there a better solution).
Many Thanks
Mick
(1) bound the DataGrid.SelectedItem to a Property in you ViewModel .
(2) send the Grid as the CommandParameter .
<DataGrid Grid.Column="2" Name="DG1" ItemsSource="{Binding}" SelectedItem="{Binding SelectedItem}" AutoGenerateColumns="False" >
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Command="{Binding Path=DataContext.DeleteMyCustomObjectCommand,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type DataGrid}}}"
CommandParameter="{Binding RelativeSource=
{RelativeSource FindAncestor,
AncestorType={x:Type DataGrid}}}" Width="20">
<Image Source="/MyThing;component/Images/delete.png" Height="16" Width="16"/>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn>
<DataGrid.Columns>
</DataGrid>
I have a wpf, mvvm app, using the catel (http://catel.codeplex.com) framework\toolkit, C# .Net 4.0. The app has a ListBox with a TextBlock and ComboBox. The ListBox and ComboBox are populated from 2 different ObservableCollection from the ViewModel. I need to save (to a db), when the user clicks a button, each row in the ListBox where the user has selected an item from the ComboBox. The SelectionChanged event does not fire for any of the ComboBoxes in the ListBox. The idea being that I add to a list (ArrayList or IList?), in the ViewModel, each time the user selects an item in a ComboBox and for what row the item has been selected.
Or am I going about this the wrong way by trying to use the ComboBoxe SelectionChanged event? I also tried iterating thru the ListBox.Items but this seems like a hak and I want to avoid ui element logic in the ViewModel if possible.
The xaml:
<Grid>
<StackPanel Orientation="Horizontal">
<Label Width="180">Field1</Label>
<ListBox Height="200"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding List1, Mode=OneWay}"
Name="listBox1"
SelectionMode="Single"
Width="300">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="290">
<TextBlock Width="90" Text="{Binding}"></TextBlock>
<ComboBox Width="180" ItemsSource="{Binding DataContext.List2, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" DisplayMemberPath="Field1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<catel:EventToCommand Command="{Binding SelectionChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}" DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
ViewModel code:
//in the ViewModel constructor
SelectionChangedCommand = new Command<SelectionChangedEventArgs>(OnSelectionChangedCommandExecute, OnSelectionChangedCommandCanExecute);
public Command<SelectionChangedEventArgs> SelectionChangedCommand { get; private set; }
private bool OnSelectionChangedCommandCanExecute()
{
return true;
}
private void OnSelectionChangedCommandExecute(SelectionChangedEventArgs e)
{
// add or update list....
}
In Command binding you have used binding which has relative source binding...
consider making these changes in binding
1) using list box as Ancestortype
2) While binding use Path=DataContext.SelectionChangedCommand otherwise it will take list box as datacontext.
<catel:EventToCommand Command="{Binding Path=DataContext.SelectionChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" DisableAssociatedObjectOnCannotExecute="False" PassEventArgsToCommand="True" />