Reputation: 165
I am using a ListBox with a DataTemplate
as shown below (xaml simplified and variable names changed).
<ListBox ItemsSource="{Binding Path=ObservCollectionItems}"
SelectedItem="{Binding Path=SelectedItemVar, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding SomeVar}" />
<Border>
<StackPanel>
<Button Content="String1"
Command="{Binding DataContext.Command1}
RelativeSource={RelativeSource FindAncestor, ListBox, 1}}" />
<Button Content="String2"
Command="{Binding DataContext.Command2}
RelativeSource={RelativeSource FindAncestor, ListBox, 1}}" />
</StackPanel>
</Border>
</StackPanel>
</DataTemplate>
<ListBox.ItemTemplate>
</ListBox>
I need the SelectedItemVar (dependency property) to update when I click on one of the buttons. SelectedItemVar is then used for the respective button's command. SelectedItemVar does update when I click on the TextBlock
or the Border
, but not when I click either button. I found a non-MVVM solution to this problem here. I do not want to add code in the file-behind to solve this, as they did in the link.
Is there a clean solution that can be done in XAML. Beyond the non-MVVM solutions, I have not found anyone with this problem. I would have thought this was fairly common.
Finally, I found this Command="{Binding DataContext.CommandName} RelativeSource={RelativeSource FindAncestor, ListBox, 1}
for the Command binding. I do not fully understand what it is doing, but I do know that the command wasn't firing when I was binding directly to CommandName
.
Upvotes: 2
Views: 3633
Reputation: 4885
You are using MVVM .... so very simple solution to that is Passing the SelectedItem as Parameter to the command of Both button and then Setting the SelectedItem with the Value of the parameter.....
public class YourViewmodel
{
//Other Variables
public YourViewModelCtor()
{
Command1= new RelayCommand(Command1Func);
}
Public SelectedVar
{
get {return value;}
Set { selectedVar=value;
OnPropertyChanged("SelectedVar");
}
}
//Other Properties
void Command1Func(object obj)
{
SelectedVar= obj as <Your Desired Type>;
//Do your thing with SelectedVar ... Do the same for Command2
}
}
<StackPanel>
<Button Command="{Binding DataContext.Command1}" CommandParameter="{Binding}"
Content="String1" />
<Button Command="{Binding DataContext.Command2}" CommandParameter="{Binding}"
Content="String2" />
</StackPanel>
This will get you the current ListBox item ferom where you clicked the button....
This should do it...... :)
Upvotes: 5
Reputation: 6142
You need some code to handle the visual behavior you want, but you don't have to put it in your view model, or your control code-behind.
I would write a Behavior (called something like SelectListBoxItemWhenClickedBehavior) that when the button is clicked, it looks up the ListBoxItem in the visual tree (using VisualTreeHelper). It can then set ListBoxItem.IsSelected = true.
The behavior does one known thing and it is set only by the visual style of the control (XAML) which knows that the button is inside a ListBoxItem. I think this keeps the separation of concerns in place for M-V-VM.
If you need help writing a behavior, let me know.
Upvotes: 2