我在用户控件中有一个带有XAML列表视图的UWP应用程序,如下所示。
<ListView x:Name="lvDevices"
Margin="12,8,0,0"
Grid.Row="4"
HorizontalContentAlignment="Stretch"
ItemTemplate="{StaticResource DeviceTemplate}"
Width="Auto"
ItemsSource="{Binding Devices}"
IsItemClickEnabled="True"
ItemClick="lvDevices_ItemClick"
d:DataContext="{d:DesignData /SampleData/DevicesVMSampleData.xaml}" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
列表视图的项目模板如下。您可以看到项模板有一个复选框,它使用双向绑定绑定到我的视图模型。
<DataTemplate x:Key="DeviceTemplate">
<Grid Margin="0" HorizontalAlignment="Stretch" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<CheckBox x:Name="chkSelected" IsChecked="{Binding Selected, Mode=TwoWay}" MinWidth="32" Grid.Column="0" Checked="chkSelected_Changed" Unchecked="chkSelected_Changed" />
<StackPanel Grid.Column="1" VerticalAlignment="Center" Margin="10,0,0,0">
<TextBlock Text="{Binding DeviceName}" Style="{StaticResource TitleTextBlockStyle}" Tag="{Binding ID}" TextWrapping="Wrap" MaxWidth="500"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="User:" Margin="0,0,10,0" Style="{StaticResource CaptionTextBlockStyle}" FontWeight="Bold" />
<TextBlock Text="{Binding User}" Style="{StaticResource CaptionTextBlockStyle}" TextWrapping="NoWrap"/>
</StackPanel>
</StackPanel>
<Button x:Name="btnInfo" Grid.Column="2" Background="Transparent" HorizontalAlignment="Right">
<Image x:Name="imgInfo" HorizontalAlignment="Right" VerticalAlignment="Center" Source="/Assets/InfoIcon-100.png" Height="50" Width="50" />
</Button>
</Grid>
</DataTemplate>
listview的datacontext设置为我的视图模型。
ucDeviceInfo.DataContext = iobj_DevicesViewModel;
所以我想要的是当用户点击列表视图中的anitem时,该项目的复选框会以复选标记更新或删除其复选标记。我认为最好的方法是设置“选定的”#39;当用户单击该行时,ViewModel中的属性为true或false,然后通知视图该属性已更改。 (项目列表是一个可观察的集合。)。
我尝试以下列方式完成此任务:
在UserControl中 - 当用户点击一行时,我使用以下代码在基页中调用一个方法:
private void lvDevices_ItemClick(object sender, ItemClickEventArgs e)
{
StartPage lobj_ParentForm;
lobj_ParentForm = ((StartPage)((Frame)Window.Current.Content).Content);
lobj_ParentForm.SendNotifyPropertyChanged( ((Device)e.ClickedItem).ID);
}
在基页中,我使用以下代码在我的ViewModel中调用方法:
public void SendNotifyPropertyChanged(int pi_DeviceID)
{
iobj_DevicesViewModel.DeviceSelectedInListView(pi_DeviceID);
}
然后在视图模型中,我更新设备的selected属性,并使用以下代码调用notify属性更改函数:
public void DeviceSelectedInListView(int pi_DeviceID)
{
Device lobj_SelectedDevice;
lobj_SelectedDevice = (from lobj_Device in Devices
where lobj_Device.ID == pi_DeviceID
select lobj_Device).ToList<Device>()[0];
lobj_SelectedDevice.Selected = !lobj_SelectedDevice.Selected;
NotifyPropertyChanged("Devices");
SelectionsChanged();
}
public void SelectionsChanged()
{
NotifyPropertyChanged("SelectedDeviceCount");
}
挑战在于,当我执行此操作并调用notify属性更改方法时,我刚刚单击的listview中项目的复选框不会更新。当用户点击列表视图中的某行时,我知道如何让复选框正确更新?
说明此问题的示例项目的链接是 Example Code
答案 0 :(得分:1)
至于你的代码 - 你几乎做得对。您的收藏参考Devices
没有变化,因此绑定不会更新整个集合,您也不会添加/删除元素,因此ObservableCollection可能已更新。在这种情况下,您需要在item的类上调用属性更改。要做到这一点,只需在Device类中实现 INotifyPropertyChanged :
public class Device : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void RaiseProperty(string name) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
private bool selected;
public bool Selected
{
get { return selected; }
set { selected = value; RaiseProperty(nameof(Selected)); }
}
// rest of the class
在此之后,每当项目内部发生变化时,您也不需要致电NotifyPropertyChanged("Devices");
,绑定将完成工作。由于你有 ObservableCollection ,我认为你根本不需要打电话。
The modified sample you have shared
我不太清楚为什么你不使用默认的ListView复选框。如果您将选择模式设置为 Multiple ,那么您将在每个项目中看到一个复选框。如果您想要处理更多操作,可以订阅 SelectionChanged 事件。带有标准复选框的示例ListView:
<ListView Name="myList" SelectionChanged="myList_SelectionChanged" SelectionMode="Multiple">
<ListView.Items>
<TextBlock Text="First item"/>
<TextBlock Text="Second item"/>
<TextBlock Text="Third item"/>
<TextBlock Text="Fifth item"/>
</ListView.Items>
</ListView>
在您的代码中,我很难说出错,因为我看不到您的商品类,我不知道您是否拥有 Selected 属性,是否实施 INotifyPropertyChanged 以及更多小事。