Xamarin.Forms无法识别ListView.ItemTemplate内控件的x:Name
问题描述
我在XAML中编写了如下ListView布局代码:
<StackLayout VerticalOptions="CenterAndExpand"> <ListView x:Name="listViewItems" Margin="1,1" BackgroundColor="White" HasUnevenRows="True" > <ListView.ItemTemplate> <DataTemplate> <ViewCell> <ContentView Padding="3" VerticalOptions="FillAndExpand" > <!-- BorderColor="Gray" BackgroundColor="{StaticResource ElementBackgroundColor}" --> <Grid BackgroundColor="White" ColumnSpacing="0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="35"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <Label x:Name="labelCode" Grid.Column="0" Grid.RowSpan="2" Text="{Binding Code}" VerticalOptions="Center" HorizontalOptions="FillAndExpand" TextColor="{StaticResource TextColor}" BackgroundColor="White" FontAttributes="Bold" FontSize="{StaticResource FontSizeLabelLittle}" /> <StackLayout Grid.Column="1" Spacing="0" Orientation="Vertical" VerticalOptions="StartAndExpand" HorizontalOptions="StartAndExpand"> <Label x:Name="labelEnglish" Text="{Binding NameEnglish}" VerticalOptions="Start" TextColor="{StaticResource TextColor}" BackgroundColor="White" FontAttributes="Bold" FontSize="{StaticResource FontSizeLabelLittle}" /> <Label x:Name="labelRussian" Text="{Binding NameRussian}" VerticalOptions="StartAndExpand" TextColor="{StaticResource TextColor}" BackgroundColor="White" FontAttributes="Bold" FontSize="{StaticResource FontSizeLabelLittle}" /> </StackLayout> </Grid> </ContentView> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout>
尝试在后台代码中执行:
labelCode.IsVisible = false;
但出现编译错误:
Severity Code Description Project File Line Suppression State
Error CS0103 The name 'labelCode' does not exist in the current context gttCompound C:\Development\Guido\Xamarin\gttCompound\gttCompound\Pages\PageViewOrSelectItem.xaml.cs 33 Active
尝试过相关解决方案但无效,需要解决如何让窗体识别这些控件的问题。
补充说明
我的需求是隐藏ListView中的空标签,避免Grid行高过大。目前通过后台构建Grid内容临时解决,但需要更优方案。我通过绑定加载所有内容,并非要填充ListView元素。
解决方案
核心原因
DataTemplate中的控件是模板化控件,每一行列表项都会根据模板生成独立的控件实例,这些实例不属于页面的直接控件树,所以无法直接通过x:Name在页面后台代码中访问。
最优实现方案:通过绑定控制可见性
利用数据绑定,在ViewModel的实体类中添加对应可见性的属性,绑定到Label的IsVisible属性:
- 修改数据实体类,添加
IsCodeVisible属性(假设实体类名为ItemModel):
public class ItemModel : INotifyPropertyChanged { // 原有属性:Code、NameEnglish、NameRussian private string _code; public string Code { get => _code; set { _code = value; OnPropertyChanged(); // 当Code为空时自动设置IsCodeVisible为false IsCodeVisible = !string.IsNullOrEmpty(value); } } private bool _isCodeVisible = true; public bool IsCodeVisible { get => _isCodeVisible; set { _isCodeVisible = value; OnPropertyChanged(); } } // 实现INotifyPropertyChanged接口 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } // 其他属性... }
- 修改XAML中的Label绑定:
<Label x:Name="labelCode" Grid.Column="0" Grid.RowSpan="2" Text="{Binding Code}" IsVisible="{Binding IsCodeVisible}" VerticalOptions="Center" HorizontalOptions="FillAndExpand" TextColor="{StaticResource TextColor}" BackgroundColor="White" FontAttributes="Bold" FontSize="{StaticResource FontSizeLabelLittle}" />
这样当Code为空时,IsCodeVisible会自动变为false,对应的Label就会隐藏,同时HasUnevenRows="True"会自动调整行高,解决空标签导致行高过大的问题。
备选方案:自定义ViewCell
如果需要更复杂的控件交互,可以创建自定义ViewCell,通过绑定或事件来控制控件状态:
- 创建自定义ViewCell类:
public class CustomItemViewCell : ViewCell { public static readonly BindableProperty IsCodeVisibleProperty = BindableProperty.Create(nameof(IsCodeVisible), typeof(bool), typeof(CustomItemViewCell), true); public bool IsCodeVisible { get => (bool)GetValue(IsCodeVisibleProperty); set => SetValue(IsCodeVisibleProperty, value); } public CustomItemViewCell() { var labelCode = new Label { FontAttributes = FontAttributes.Bold, FontSize = (double)Application.Current.Resources["FontSizeLabelLittle"], TextColor = (Color)Application.Current.Resources["TextColor"], BackgroundColor = Color.White, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.FillAndExpand }; labelCode.SetBinding(Label.TextProperty, "Code"); labelCode.SetBinding(Label.IsVisibleProperty, new Binding(nameof(IsCodeVisible), source: this)); // 构建其他控件... var grid = new Grid { BackgroundColor = Color.White, ColumnSpacing = 0, ColumnDefinitions = { new ColumnDefinition { Width = 35 }, new ColumnDefinition { Width = GridLength.Star } } }; grid.Children.Add(labelCode, 0, 0); // 添加其他控件到Grid... View = new ContentView { Padding = new Thickness(3), VerticalOptions = LayoutOptions.FillAndExpand, Content = grid }; } }
- 在XAML中使用自定义ViewCell:
<ListView x:Name="listViewItems" Margin="1,1" BackgroundColor="White" HasUnevenRows="True" > <ListView.ItemTemplate> <DataTemplate> <local:CustomItemViewCell IsCodeVisible="{Binding IsCodeVisible}" /> </DataTemplate> </ListView.ItemTemplate> </ListView>
内容的提问来源于stack exchange,提问作者GuidoG

