将按钮命令绑定到“外部”数据上下文的属性时遇到了一些问题。
下图显示了我的布局。我正在尝试将“清除”按钮的CommandParameter(以红色标出)绑定到LocationId。 ItemsControl重复ObservableCollection的位置(请参阅下面的位置定义)。
“清除”按钮基本上是尝试删除附加到位置的地址,以清除DataGrid。为此,我需要将LocationId传递给ViewModel。
实际命令被完美触发,但CommandParameter上的绑定不太正确。
以下是Location& amp;的基础课程。地址:
class Location
{
int Id;
ObservableCollection<Address> Addresses;
}
class Address
{
string AddressText;
}
以下是XAML评论的三个替代尝试&amp;错误消息:
<ItemsControl ItemsSource="{Binding Locations, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Id}"/>
<sdk:DataGrid x:Name="ResponseDataGrid" ItemsSource="{Binding Addresses}">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Response" Width="*" Binding="{Binding AddressText}"/>
<sdk:DataGridTemplateColumn Width="100">
<sdk:DataGridTemplateColumn.HeaderStyle>
<Style TargetType="sdk:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Button Content="Clear"
Command="{Binding DataContext.ClearLocationCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding Id, RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>
<!--System.Windows.Data Error: BindingExpression path error: 'Id' property not found on 'System.Windows.Controls.ItemsControl' -->
<!--CommandParameter="{Binding ItemsSource.Id, RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>-->
<!--System.Windows.Data Error: BindingExpression path error: 'Id' property not found on 'System.Collections.ObjectModel.ObservableCollection`1[UI.Location]' -->
<!--This gives me the ID but uses a specific index so only works for the first repeated Location-->
<!--CommandParameter="{Binding ItemsSource[0].Id, RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>-->
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</sdk:DataGridTemplateColumn.HeaderStyle>
<sdk:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Accept">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction
Command="{Binding DataContext.SelectedAddressCommand , RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding SelectedItem, RelativeSource={RelativeSource AncestorType=sdk:DataGrid}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
从错误中看,按钮似乎无法完全看到重复的Location对象,它可以看到Locations的集合或特定的索引位置,但不能看到我需要的重复生成的位置!
谢谢!
答案 0 :(得分:1)
所以你有一个带有ObservableCollection<Location>
的ViewModel并点击Clear清除指定位置的ObservableCollection<Address>
,对吗?
为什么不将Clear命令放入Location类?我不知道这个命令触发的逻辑,但这样做你将能够访问正确的位置Id属性。
编辑:这是我工作的例子:
<强>类强>
public class Location
{
public Location(int id, IEnumerable<Address> addresses)
{
this.Id = id;
this.Addresses =new ObservableCollection<Address>(addresses);
this.ClearLocationCommand = new RelayCommand<int>(e => MessageBox.Show(string.Format("Clear command called on Location {0}", this.Id)));
}
public int Id { get; set; }
public ObservableCollection<Address> Addresses { get; set; }
public ICommand ClearLocationCommand { get; set; }
}
public class Address
{
public Address(string text)
{
this.AddressText = text;
}
public string AddressText { get; set; }
}
public class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainWindowViewModel()
{
Locations = new ObservableCollection<Location>(new []
{
new Location(1, new [] { new Address("A1") }),
new Location(2, new [] { new Address("A2"), new Address("A3"), }),
});
}
public ObservableCollection<Location> Locations { get; set; }
private void OnPropertyChanged(string porpertyName)
{
var e = this.PropertyChanged;
if (e != null)
{
e(this, new PropertyChangedEventArgs(porpertyName));
}
}
}
<强> XAML 强>
<Window x:Class="TestBindingButtons.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:TestBindingButtons="clr-namespace:TestBindingButtons" Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<TestBindingButtons:MainWindowViewModel />
</Window.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Locations, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel VerticalAlignment="Stretch" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Id}"/>
<DataGrid x:Name="ResponseDataGrid" ItemsSource="{Binding Addresses}">
<DataGrid.Columns>
<DataGridTextColumn Header="Response" Width="*" Binding="{Binding AddressText}"/>
<DataGridTemplateColumn Width="100">
<DataGridTemplateColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Button Content="Clear"
Command="{Binding DataContext.ClearLocationCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
/>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.HeaderStyle>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button Content="Accept">
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Window>
PD: 我没有发布RelayCommand的实现,使用你自己的。 我没有使用你的“sdk”框架,只是简单的微软东西。
答案 1 :(得分:1)
如果将ClearLocationCommand
属性移动到Location
类,请记住更改以下绑定:
<Button Content="Clear"
Command="{Binding DataContext.ClearLocationCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
CommandParameter="{Binding Id, RelativeSource={RelativeSource AncestorType=ItemsControl}}"
/>
为:
<Button Content="Clear"
Command="{Binding ClearLocationCommand}"
CommandParameter="{Binding Id}"
/>
因为每个外部Location
对象现在都有自己的清除命令,并且您已经在该项目行中的正确DataContext
。