WPF MVVM中ComboBox数据不在列表时显示“未找到数据”
WPF ComboBox显示“Not found data”的XAML实现方案
你之前写的Trigger没起作用,核心原因是:当数据库返回的值不在ComboBox的选项列表里时,SelectedItem确实会变成null,但ComboBox的Text属性会优先显示绑定的原始值,而非你通过Trigger设置的提示文本——因为绑定的优先级高于Trigger的Setter。
下面给你几个以XAML为主的可行方案:
方案1:验证规则+DataTrigger组合
利用WPF的验证机制,当绑定的值不在选项中时触发错误,再用DataTrigger显示提示文本。
第一步:后台编写验证规则类
public class ComboBoxItemValidationRule : ValidationRule { public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo) { var comboBox = (ComboBox)ValidationStepHelper.GetCurrentObject(); if (comboBox.ItemsSource != null && !comboBox.ItemsSource.Cast<object>().Contains(value)) { return new ValidationResult(false, "Not found data"); } return ValidationResult.ValidResult; } }
第二步:XAML配置ComboBox
<ComboBox x:Name="MyComboBox" ItemsSource="{Binding Options}" SelectedValue="{Binding SelectedData}"> <ComboBox.Resources> <Style TargetType="ComboBox"> <Style.Triggers> <DataTrigger Binding="{Binding (Validation.HasError), ElementName=MyComboBox}" Value="True"> <Setter Property="Text" Value="Not found data"/> </DataTrigger> </Style.Triggers> </Style> </ComboBox.Resources> <ComboBox.SelectedValueBinding> <Binding Path="SelectedData"> <Binding.ValidationRules> <local:ComboBoxItemValidationRule ValidationStep="UpdatedValue"/> </Binding.ValidationRules> </Binding> </ComboBox.SelectedValueBinding> </ComboBox>
方案2:MultiBinding+转换器
直接判断绑定的值是否在选项列表里,无需验证机制,逻辑更简洁。
第一步:后台编写转换器
public class ComboBoxItemExistConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var selectedValue = values[0]; var itemsSource = values[1] as IEnumerable; if (selectedValue == null || itemsSource == null) return selectedValue; return itemsSource.Cast<object>().Contains(selectedValue) ? selectedValue : "Not found data"; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
第二步:XAML配置
<Window.Resources> <local:ComboBoxItemExistConverter x:Key="ItemExistConverter"/> </Window.Resources> <ComboBox ItemsSource="{Binding Options}"> <ComboBox.Text> <MultiBinding Converter="{StaticResource ItemExistConverter}"> <Binding Path="SelectedData"/> <Binding Path="ItemsSource" RelativeSource="{RelativeSource Self}"/> </MultiBinding> </ComboBox.Text> <ComboBox.SelectedValue> <Binding Path="SelectedData"/> </ComboBox.SelectedValue> </ComboBox>
方案3:修改ComboBox模板(最灵活)
直接修改控件模板,在没有匹配项时显示自定义文本块,完全通过XAML控制显示逻辑:
<ComboBox ItemsSource="{Binding Options}" SelectedValue="{Binding SelectedData}"> <ComboBox.Template> <ControlTemplate TargetType="ComboBox"> <Grid> <ToggleButton x:Name="ToggleButton" Template="{StaticResource ComboBoxToggleButtonTemplate}"/> <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding SelectedItem}" ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" Margin="3,3,23,3" VerticalAlignment="Center"/> <TextBlock x:Name="NotFoundText" Text="Not found data" Margin="3,3,23,3" VerticalAlignment="Center" Visibility="Collapsed"/> <Popup x:Name="Popup" Placement="Bottom" IsOpen="{TemplateBinding IsDropDownOpen}" AllowsTransparency="True" Focusable="False"> <Border x:Name="DropDownBorder" Background="White" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1"> <ScrollViewer x:Name="DropDownScrollViewer"> <ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained"/> </ScrollViewer> </Border> </Popup> </Grid> <ControlTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding SelectedItem, RelativeSource={RelativeSource Self}}" Value="{x:Null}"/> <Condition Binding="{Binding SelectedValue, RelativeSource={RelativeSource Self}}" Value="{x:Null}" Negate="True"/> </MultiDataTrigger.Conditions> <Setter TargetName="ContentPresenter" Property="Visibility" Value="Collapsed"/> <Setter TargetName="NotFoundText" Property="Visibility" Value="Visible"/> </MultiDataTrigger> <!-- 可保留ComboBox默认模板中的其他触发器,如IsEnabled、IsMouseOver等交互效果 --> </ControlTemplate.Triggers> </ControlTemplate> </ComboBox.Template> </ComboBox>
内容的提问来源于stack exchange,提问作者user19161290
相关产品推荐
相关产品推荐

