如何将 WPF ListBoxItem 的 IsEnabled 属性绑定到其源项的属性?

Posted

技术标签:

【中文标题】如何将 WPF ListBoxItem 的 IsEnabled 属性绑定到其源项的属性?【英文标题】:How to bind the IsEnabled Property of a WPF ListBoxItem to a Property of its Source Item? 【发布时间】:2021-09-25 03:41:31 【问题描述】:

我有一个 ObservableCollectionItemSource 的 ListBox:

public partial class HomePage : Page

    public ObservableCollection<DaemonFile> Files  get; private set; 
    private readonly MainWindow MainWindow;

    public HomePage(MainWindow MainWindow)
    
        Files = new ObservableCollection<DaemonFile>();

        this.MainWindow = MainWindow;

        InitializeComponent();

        ListOfFiles.ItemsSource = Files;
    
    ...


我的DaemonFile 中有以下属性:

public class DaemonFile : INotifyPropertyChanged

    public enum ProcessStates : int
    
        CREATED = 0,
        CONVERTED = 1,
        UPLOADING = 2,
        FINISHED = 3
    
    private ProcessStates ProcessStateValue = ProcessStates.CREATED;
    public ProcessStates ProcessState 
     
        get  return this.ProcessStateValue;  
        set 
        
           if (value != this.ProcessStateValue)
           
               this.ProcessStateValue = value;
               NotifyPropertyChanged();
           
         
     
    ...
    private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
    
        if (PropertyChanged != null)
        
            mainWindow.WriteLine("Property " + propertyName + " Changed!");
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
         else
        
            mainWindow.WriteLine("Cant fire event!");
        
    

文件转换完成后,ProcessState 会异步更新。 我想我需要绑定此属性并将其放入IsEnabled 的设置器中。

        <Style x:Key="Item" TargetType="x:Type ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="x:Type ListBoxItem">
                        <Grid Background="TemplateBinding Background">
                            <ContentPresenter 
                                    ContentTemplate="TemplateBinding ContentTemplate"
                                    Content="TemplateBinding Content"
                                    HorizontalAlignment="TemplateBinding HorizontalContentAlignment"
                                    Margin="TemplateBinding Padding">
                            </ContentPresenter>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <DataTrigger Binding="Binding ProcessState" Value="0">
                    <Setter Property="IsEnabled" Value="False"/>
                </DataTrigger> 
            </Style.Triggers>
        </Style>   

每当DaemonFile 将其ProcessState 更改为1 或更高时,我如何才能实现相应的ListBoxItem 切换为启用?

我不希望用户能够在文件完成转换之前上传文件

我还可以将isEnabled 属性添加到我的DaemonFile 以简化一些事情。但这并不能解决我的绑定问题。

【问题讨论】:

【参考方案1】:

您不需要那个 ControlTemplate。

一个简单的 DataTrigger 应该可以工作:

<Style x:Key="ItemStyle" TargetType="x:Type ListBoxItem">
    <Style.Triggers>
        <DataTrigger Binding="Binding ProcessState" Value="0">
            <Setter Property="IsEnabled" Value="False"/>
        </DataTrigger>
    </Style.Trigers>
</Style>

以防万一:

<ListBox x:Name="ListOfFiles"
         ItemContainerStyle="StaticResource ItemStyle" ...>

【讨论】:

如果我这样做,它会被禁用但未启用。所以我根本无法与之互动。我还尝试做另一个触发器来启用它,但这似乎不起作用。顺便说一句,谢谢您的快速回答。 如果您没有在其他任何地方设置 IsEnabled,它将被启用。当然,不要使用您问题中的 ControlTemplate。 我是否需要在更新进程状态时触发属性更改事件? 好的。我已经在 DaemonFile 类中实现了 INotifyPropertyChanged。设置进程状态时我调用 PropertyChanged.Invoke(this, new PropertyChangedEventArgs(Name)); 它正在更新状态,但 ui 对更改没有反应。当我将 CREATED 状态的值更改为 0 以外的值时,它会被启用。

以上是关于如何将 WPF ListBoxItem 的 IsEnabled 属性绑定到其源项的属性?的主要内容,如果未能解决你的问题,请参考以下文章

WPF中如何给listboxitem添加单机时间

无法使用 DataTemplate WPF 将 InputBinding 应用于整个 ListBoxItem

获取 ListBoxItem 的索引 - WPF

如何知道一个显示的listboxItem是否在WPF ListBox中?

wpf listboxitem 双击事件

选择时如何让wpf listboxitem拉伸列表框的整个高度