Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF从代码隐藏向现有样式添加触发器_C#_Wpf - Fatal编程技术网

C# WPF从代码隐藏向现有样式添加触发器

C# WPF从代码隐藏向现有样式添加触发器,c#,wpf,C#,Wpf,我有一个TabControl,其中一些选项卡是用XAML声明的。我想添加新选项卡,并将其IsEnabled属性绑定到其内容的某些属性: for (int i = 0; i < context.Pictures.Count; ++i) { var tabItem = new TabItem(); var title = "Some title" tabItem.Header = title;

我有一个
TabControl
,其中一些选项卡是用XAML声明的。我想添加新选项卡,并将其
IsEnabled
属性绑定到其内容的某些属性:

    for (int i = 0; i < context.Pictures.Count; ++i)
    {
        var tabItem = new TabItem();
        var title = "Some title"
        tabItem.Header = title;
        var image = new Image();
        Binding sourceBinding = new Binding(nameof(context.Pictures) + $"[{i}]");
        sourceBinding.Source = context;
        image.SetBinding(Image.SourceProperty, sourceBinding);
        image.Width = 800;
        image.Height = 600;
        
        DataTrigger isEnabledTrigger = new DataTrigger() { Binding = sourceBinding, Value = null };
        isEnabledTrigger.Setters.Add(new Setter(TabItem.IsEnabledProperty, false));

        tabItem.Content = image;
        tabControl.Items.Add(tabItem);
    }
for(int i=0;i
如果内部图片为
null
(应用
isEnabledTrigger
),我想禁用选项卡。这里的问题是
tabItem
的样式是从包含它的
tabControl
派生出来的,所以我不能用触发器创建一个样式并将其应用于
tabItem
。当然,我可以复制原始样式并硬编码,但我认为这不是解决问题的好方法

所以,要解决我的问题,我有两个想法:

  • 创建现有样式的浅层副本,添加触发器并应用它
  • 从XAML加载原始样式,添加触发器并应用它(可能很困难,因为它位于另一个项目中)

  • 是否有更合理的方法将
    TabControl
    s
    IsEnabled
    绑定到包含的
    Image
    s值?

    不要直接添加
    TabItem
    。使用数据模型。这是所有项目控制的推荐方法。然后为数据模型定义一个
    DataTemplate
    ,并将其分配给
    TabControl.ContentTemplate
    。 使用
    选项卡control.ItemTemplate
    布局标题。
    选项卡control.ItemContainerStyle
    定义
    样式
    ,可以非常轻松地设置所需的触发器。使用C#进行布局从来都不是一个好主意。始终使用XAML

    见:

    最小模型类应如下所示:

    PictureModel.cs

    // All binding source models must implement INotifyPropertyChanged
    public class PictureModel : INotifyPropertyChanged
    {
      private string title;
      public string Title
      {
        get => this.title;
        set
        {
          this.title = value;
          OnPropertyChanged();
        }
      }
    
      private string source;
      public string Source
      {
        get => this.source;
        set
        {
          this.source = value;
          OnPropertyChanged();
        }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    
    class ViewModel : INotifyPropertyChanged
    {
      public ObservableCollection<PictureModel> Pictures { get; }
    
      private void CreateTabItems(Context context)
      {
        foreach (string imageSource in context.Pictures)
        {
          var pictureModel = new PictureModel() 
          {
            Title = "Some Title",
            Source = imageSource
          };
          this.Pictures.Add(pictureModel);
        }
      }
    }
    
    ViewModel.cs

    // All binding source models must implement INotifyPropertyChanged
    public class PictureModel : INotifyPropertyChanged
    {
      private string title;
      public string Title
      {
        get => this.title;
        set
        {
          this.title = value;
          OnPropertyChanged();
        }
      }
    
      private string source;
      public string Source
      {
        get => this.source;
        set
        {
          this.source = value;
          OnPropertyChanged();
        }
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
      {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    
    class ViewModel : INotifyPropertyChanged
    {
      public ObservableCollection<PictureModel> Pictures { get; }
    
      private void CreateTabItems(Context context)
      {
        foreach (string imageSource in context.Pictures)
        {
          var pictureModel = new PictureModel() 
          {
            Title = "Some Title",
            Source = imageSource
          };
          this.Pictures.Add(pictureModel);
        }
      }
    }
    
    类视图模型:INotifyPropertyChanged
    {
    公共可观察收集图片{get;}
    私有void CreateTabItems(上下文)
    {
    foreach(context.Pictures中的字符串imageSource)
    {
    var pictureModel=new pictureModel()
    {
    Title=“一些标题”,
    源=图像源
    };
    this.Pictures.Add(pictureModel);
    }
    }
    }
    
    main window.xaml

    <Window>
      <Window.DataContext>
        <ViewModel />
      </Window.DataContext>
    
        <!-- Layout the tab content -->
      <TabControl ItemsSource="{Binding Pictures}">
        <TabControl.ContentTemplate>
          <DataTemplate DataType="{x:Type viewModels:PictureModel}">
            <Image Source="{Binding Source}" />
          </DataTemplate>
        </TabControl.ContentTemplate>
    
        <!-- Layout the tab header -->
        <TabControl.ItemTemplate>
          <DataTemplate DataType="{x:Type viewModels:PictureModel}">
            <TextBlock Text="{Binding Title}" />
          </DataTemplate>
        </TabControl.ItemTemplate>
    
        <!-- Setup triggers. The DataContext is the current data model -->
        <TabControl.ItemContainerStyle>
          <Style TargetType="TabItem">
            <Style.Triggers>
              <DataTrigger Binding="{Binding Source}" Value="{x:Null}">
                <Setter Property="IsEnabled" Value="False" />
              </DataTrigger>
            </Style.Triggers>
          </Style>
        </TabControl.ItemContainerStyle>
      </TabControl>
    </Window>
    

    您应该根据当前的
    样式创建
    样式

    Style style = new Style(typeof(TabItem))
    {
        BasedOn = FindResource(typeof(TabItem)) as Style
    };
    DataTrigger isEnabledTrigger = new DataTrigger() { Binding = sourceBinding, Value = null };
    isEnabledTrigger.Setters.Add(new Setter(TabItem.IsEnabledProperty, false));
    style.Triggers.Add(isEnabledTrigger);
    tabItem.Style = style;
    

    …取决于当前
    样式的应用方式


    这就是使用
    DataTrigger
    扩展现有
    样式的方法,这是解决此问题的好方法。

    正确的方法是为选项卡内容定义
    DataTemplate
    ,并将其分配给
    TabControl.ContentTemplate