【问题标题】:Binding DataTemplate items events to command in viewmodel将 DataTemplate 项目事件绑定到视图模型中的命令
【发布时间】:2019-08-31 15:03:18
【问题描述】:

我正在构建具有列表框的 WPF MVVM 应用程序,该列表框的项目模板具有组合框和文本框(项目模板位于单独的资源字典中),我将模板中的 selectionchanged 事件和 textchanged 事件绑定到我的视图模型中的命令,它是在运行时完美运行,但问题是在设计时它给了我 triggers.null 错误,xamlview 没有显示但给了我 XamlParseException。

我在 MVVMlight 中尝试了 CommandtoEvent,但没有成功,还尝试了 AttachedCommandBehavior,但也没有成功,此外还尝试将整个模板移动到视图中(作为视图中的项目模板而不是资源字典,但没有也不行。

听起来交互性在放置在模板中时会出现此错误,但我不知道如何解决它

附加的 Xaml 代码用于列表框的数据模板

<DataTemplate x:Key="AllPanelsFilter">
    <Grid Margin="0 0 30 0" >
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>


        <ComboBox  ItemsSource="{Binding AllConditionsList}" SelectedItem="{Binding SelectedCondition}" >

                <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged" >

                    <i:InvokeCommandAction Command="{Binding DataContext.ApplyAllPanelsFiltersCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor} }"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>

        </ComboBox>
        <TextBox  Grid.Row="1" Style="{StaticResource SearchTextBox}" Text="{Binding SearchString, UpdateSourceTrigger=PropertyChanged}" >
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <i:InvokeCommandAction Command="{Binding DataContext.ApplyAllPanelsFiltersCommand, RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}  }"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>

        </TextBox>

    </Grid>
</DataTemplate>

我收到此错误 >> 'System.Windows.Controls.ComboBox'.'Triggers' 为空。

这是视图模型:

    public ObservableCollection<ViewNewPanelsPair> AllViewNewPanelsPairs { get; set; }
    public ViewNewPanelsPair CurrentViewNewPanelsPair { get; set; }
    public View CurrentView { get; set; }
    public ViewsFilter ViewsFilter { get; set; }
    public ViewsFilterCommand ViewsFilterCommand { get; set; }
    public AddAllPanelsFilterCommand AddAllPanelsFilterCommand { get; set; }
    public RemoveAllPanelsFilterCommand RemoveAllPanelsFilterCommand { get; set; }

    public ApplyAllPanelsFiltersCommand ApplyAllPanelsFiltersCommand { get; set; }
    public ObservableCollection<AllPanelsFilter> AllPanelsFilters { get; set; }


    private AllPanelsFilter selectedAllPanelsFilter;

    public AllPanelsFilter SelectedAllPanelsFilter
    {
        get { return selectedAllPanelsFilter; }
        set
        {
            selectedAllPanelsFilter = value;
            OnPropertyChanged("selectedAllPanelsFilter");
        }
    }



    public LevelPanelsViewModel(List<FamilyInstance> allPanels, List<FamilyInstance> oldOanels, List<ViewNewPanelsPair> allViewNewPanelsPairs, View currentView)
    {
        this.FilteredAllPanels = new ObservableCollection<FamilyInstance>(allPanels);
        this.AllPanels = new ObservableCollection<FamilyInstance>(allPanels);
        this.OldPanels = new ObservableCollection<FamilyInstance>(oldOanels);
        this.AllViewNewPanelsPairs = new ObservableCollection<ViewNewPanelsPair>(allViewNewPanelsPairs);
        this.ViewNewPanelsPairs = new ObservableCollection<ViewNewPanelsPair>(allViewNewPanelsPairs);
        this.CurrentView = currentView;
        this.ViewsFilter = new ViewsFilter();
        this.ViewsFilterCommand = new ViewsFilterCommand(this, this.ViewsFilter);
        this.ViewsFilterCommand.Execute(null);
        this.CurrentViewNewPanelsPair = this.ViewNewPanelsPairs[0] ; // makes first view selected at startup
        this.AllPanelsFilters = new ObservableCollection<AllPanelsFilter>();
        this.AddAllPanelsFilterCommand = new AddAllPanelsFilterCommand(this);
        this.RemoveAllPanelsFilterCommand = new RemoveAllPanelsFilterCommand(this);
        this.ApplyAllPanelsFiltersCommand = new ApplyAllPanelsFiltersCommand(this);


    }

    public LevelPanelsViewModel()
    {

    }
    public void DragOver(IDropInfo dropInfo)
    {
        GongHelper.DragOverCopy(dropInfo);
    }

    public void Drop(IDropInfo dropInfo)
    {
        GongHelper.DropDefault(dropInfo);
        //GongHelper.DropCopy<FamilyInstance>(dropInfo);
       // CurrentViewNewPanelsPair.IsViewPanelsNotEmpty = CurrentViewNewPanelsPair.SelectedNewPanels.Count > 0;
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;

}

这里是命令类:

public class ApplyAllPanelsFiltersCommand : ICommand
{
    public LevelPanelsViewModel VM { get; set; }
    public ObservableCollection<AllPanelsFilter> AllPanelsFilters { get; set; }
    public List<FamilyInstance> TemporaryAllPanels { get; set; }

    public ApplyAllPanelsFiltersCommand(LevelPanelsViewModel VM)
    {
        this.VM = VM;
        this.AllPanelsFilters = VM.AllPanelsFilters;
        this.TemporaryAllPanels = new List<FamilyInstance>(VM.AllPanels);
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        this.TemporaryAllPanels = new List<FamilyInstance>(VM.AllPanels);
        foreach (AllPanelsFilter AllPanelsFilter in AllPanelsFilters)
        {
            string FilterText = AllPanelsFilter.SearchString;
            if (!string.IsNullOrEmpty(FilterText))
            {
                switch (AllPanelsFilter.SelectedCondition)
                {
                    case AllPanelsFilter.Contains:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => x.Name.ToLower().Contains(FilterText.ToLower())).ToList();
                        break;
                    case AllPanelsFilter.DoesNotContain:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => !x.Name.ToLower().Contains(FilterText.ToLower())).ToList();
                        break;
                    case AllPanelsFilter.BeginsWith:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => x.Name.ToLower().StartsWith(FilterText.ToLower())).ToList();
                        break;
                    case AllPanelsFilter.DoesNotBeginWith:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => !x.Name.ToLower().StartsWith(FilterText.ToLower())).ToList();
                        break;
                    case AllPanelsFilter.EndsWith:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => x.Name.ToLower().EndsWith(FilterText.ToLower())).ToList();
                        break;
                    case AllPanelsFilter.DoesNotEndWith:
                        TemporaryAllPanels = TemporaryAllPanels.Where(x => !x.Name.ToLower().EndsWith(FilterText.ToLower())).ToList();
                        break;

                }
            }

        }
        //clear all panels observable collection
        int count = VM.FilteredAllPanels.Count;
        for (int i = 0; i < count; i++)
        {
            VM.FilteredAllPanels.RemoveAt(0);
        }
        //sort temporary list
        TemporaryAllPanels.OrderBy(x => x.Name);
        //fill observable collection from temporary list
        TemporaryAllPanels.ForEach(x => VM.FilteredAllPanels.Add(x));
    }
    public event EventHandler CanExecuteChanged;


}

AllPanelsFilter 类:

public class AllPanelsFilter : INotifyPropertyChanged
{
    public const string Contains = "contains";
    public const string DoesNotContain = "does not contain";
    public const string BeginsWith = "begins with";
    public const string DoesNotBeginWith = "does not begin with";
    public const string EndsWith = "ends with";
    public const string DoesNotEndWith = "does not end with";
    public List<string> AllConditionsList { get; set; }


    private string searchString;

    public string SearchString
    {
        get { return searchString; }
        set
        {
            searchString = value;
            OnPropertyChanged("SearchString");
        }
    }

    private string selectedCondition;

    public string SelectedCondition
    {
        get { return selectedCondition; }
        set
        {
            selectedCondition = value;
            OnPropertyChanged("SelectedCondition");
        }
    }



    public AllPanelsFilter()
    {
        this.SearchString = "";
        this.AllConditionsList = new List<string>() { Contains, DoesNotContain, BeginsWith, DoesNotBeginWith, EndsWith, DoesNotEndWith };
        this.SelectedCondition = Contains;
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}

【问题讨论】:

  • 设置DataTemplate.DataType 属性:DataTemplate DataType="MyViewModelType" /&gt; 以在设计期间获得设计人员支持。
  • @BionicCode ,感谢您的快速回复,我这样做了&lt;DataTemplate x:Key="AllPanelsFilter" DataType="{x:Type VM:LevelPanelsViewModel}"&gt; 但不幸的是它没有用!!
  • 鉴于代码正在构建和执行,并且只有设计器显示错误错误,您可以尝试清理和重建解决方案并重新启动 VS。 ApplyAllPanelsFiltersCommand 声明在哪个类型上,LevelPanelsViewModel
  • @BionicCode ,回答您的问题:是的 ApplyAllPanelsFiltersCommandLevelPanelsViewModel 中声明,我尝试清理、重建和重新启动 VS,但这也没有用。
  • @BionicCode 找出导致问题的原因我尝试了这个:我从头开始新的 WPF 项目并尝试在内部添加交互性和一个模板,并且在设计时和运行时运行良好,但我发现新项目具有 AnyCpu 处理器架构,我将其转换为 X64(与我的原始项目相同),它再次给了我同样的错误,但问题是当我恢复到我的原始项目并将其从 x64 更改为 AnyCPU 希望这解决了它,令我惊讶的是它没有解决问题! ,我真的很困惑,没有想法。

标签: wpf xaml


【解决方案1】:

问题已通过使用 Microsoft Expression Blend Software Development Kit (SDK) for .NET 4 中的交互 dll 解决,可在此处下载:“https://www.microsoft.com/en-us/download/details.aspx?id=10801”,问题只是旧的交互 dll 没有'不支持 x64(这是我的项目架构),但这个新的支持。感谢@BionicCode 从一开始就通过分享想法和支持我来帮助我。

【讨论】:

    【解决方案2】:

    从列表框中删除 itemssource 解决了问题,但不知道将 itemsource 放在哪里以确保在运行时绑定而不会出现此错误

    【讨论】:

      猜你喜欢
      • 2014-11-08
      • 2011-09-01
      • 1970-01-01
      • 2022-10-25
      • 2013-03-22
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多