Привязка к команде с параметром в установщике стилей WPF
У меня есть настольное приложение, написанное на WPF, которое имеет элемент управления, который работает с динамически создаваемыми вкладками. Я связал CloseTabCommand со свойством CloseCommand элемента управления через установщик стилей.
<Style TargetType="cc:SearchTab">
<Setter Property="CloseCommand" Value="{Binding CloseTabCommand}"/>
<Setter Property="CaptionImage" Value="{dx:DXImage Image=Lookup&Reference_16x16.png}"/>
</Style>
Я хочу передать {RelativeSource Self} в качестве параметра команды в CloseTabCommand, чтобы получить фактический экземпляр вкладки и удалить его из коллекции вкладок из-за кода. Но я понятия не имею, как архивировать это.
Вот полное определение представления xaml:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dxthm="clr-namespace:DevExpress.Xpf.Utils.Themes;assembly=DevExpress.Xpf.Core.v16.2"
xmlns:dxr="http://schemas.devexpress.com/winfx/2008/xaml/ribbon"
xmlns:dxb="http://schemas.devexpress.com/winfx/2008/xaml/bars"
xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
xmlns:dxe="http://schemas.devexpress.com/winfx/2008/xaml/editors"
xmlns:view="clr-namespace:ConfigOcean.View"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
xmlns:cc="clr-namespace:Arc.Stork.ConfigOcean.CustomControls"
x:Class="Arc.Stork.ConfigOcean.View.MainView"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<UserControl.Resources>
<ResourceDictionary>
<view:UsersSearchView x:Key="UsersSearch"/>
<view:CountriesDetailsView x:Key="CountriesDetails"/>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<DockPanel>
<dxr:RibbonControl x:Name="ribbonMain" DockPanel.Dock="Top" RibbonStyle="Office2007" ApplicationButtonLargeIcon="/Images/icon.png" SelectedPage="{Binding SelectedPage, Mode=OneWayToSource}">
<dxr:RibbonControl.ApplicationMenu>
<dxr:ApplicationMenu>
<dxb:BarButtonItem x:Name="bbiAbout" Content="About" Glyph="{dx:DXImage Image=Info_16x16.png}" LargeGlyph="{dx:DXImage Image=Info_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiHelp" Content="Help" Glyph="{dx:DXImage Image=Question_16x16.png}" LargeGlyph="{dx:DXImage Image=Question_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiPrint" Content="Print" LargeGlyph="{dx:DXImage Image=Print_32x32.png}" Glyph="{dx:DXImage Image=Print_16x16.png}"/>
<dxb:BarSubItem x:Name="bsiExport" Content="Export to..." Glyph="{dx:DXImage Image=Export_32x32.png}" LargeGlyph="{dx:DXImage Image=Export_32x32.png}">
<dxb:BarButtonItem x:Name="bbiExportToXlsx" Content="XLSX" Glyph="{dx:DXImage Image=ExportToXLSX_32x32.png}" LargeGlyph="{dx:DXImage Image=ExportToXLSX_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiExportToCsv" Content="CSV" Glyph="{dx:DXImage Image=ExportToCSV_32x32.png}" LargeGlyph="{dx:DXImage Image=ExportToCSV_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiExportToPdf" Content="PDF" Glyph="{dx:DXImage Image=ExportToPDF_32x32.png}" LargeGlyph="{dx:DXImage Image=ExportToPDF_32x32.png}"/>
</dxb:BarSubItem>
</dxr:ApplicationMenu>
</dxr:RibbonControl.ApplicationMenu>
<dxr:RibbonDefaultPageCategory>
<dxr:RibbonPage x:Name="pageActions" Caption="Actions">
<dxr:RibbonPageGroup x:Name="rpgActions" Caption="File">
<dxb:BarButtonItem x:Name="bbiClose" Content="Close" Glyph="{dx:DXImage Image=Close_32x32.png}" LargeGlyph="{dx:DXImage Image=Close_32x32.png}"/>
<dxb:BarItemLinkSeparator/>
<dxb:BarButtonItem x:Name="bbiRefresh" Content="Refresh" Glyph="{dx:DXImage Image=Refresh2_32x32.png}" LargeGlyph="{dx:DXImage Image=Refresh2_32x32.png}"/>
</dxr:RibbonPageGroup>
<dxr:RibbonPageGroup x:Name="rpgEdit" Caption="Edit">
<dxb:BarButtonItem x:Name="bbiEdit" Content="Edit" Glyph="{dx:DXImage Image=Edit_32x32.png}" LargeGlyph="{dx:DXImage Image=Edit_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiSave" Content="Save" Glyph="{dx:DXImage Image=Save_32x32.png}" LargeGlyph="{dx:DXImage Image=Save_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiCancel" Content="Cancel" Glyph="{dx:DXImage Image=Cancel_32x32.png}" LargeGlyph="{dx:DXImage Image=Cancel_32x32.png}" IsVisible="False"/>
<dxb:BarButtonItem x:Name="bbiClear" Content="Clear" LargeGlyph="{dx:DXImage Image=Clear_32x32.png}" Glyph="{dx:DXImage Image=Clear_16x16.png}"/>
</dxr:RibbonPageGroup>
<dxr:RibbonPageGroup x:Name="rpgClipboard" Caption="Clipboard">
<dxb:BarButtonItem x:Name="bbiCut" Content="Cut" Glyph="{dx:DXImage Image=Cut_32x32.png}" LargeGlyph="{dx:DXImage Image=Cut_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiCopy" Content="Copy" Glyph="{dx:DXImage Image=Copy_32x32.png}" LargeGlyph="{dx:DXImage Image=Copy_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiPaste" Content="Paste" Glyph="{dx:DXImage Image=Paste_32x32.png}" LargeGlyph="{dx:DXImage Image=Paste_32x32.png}"/>
</dxr:RibbonPageGroup>
<dxr:RibbonPageGroup x:Name="rpgEntity" Caption="Entity">
<dxb:BarButtonItem x:Name="bbiClone" Content="Clone" Glyph="{dx:DXImage Image=Merge_32x32.png}" LargeGlyph="{dx:DXImage Image=Merge_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiInsert" Content="Insert" Glyph="{dx:DXImage Image=Add_32x32.png}" LargeGlyph="{dx:DXImage Image=Add_32x32.png}"/>
<dxb:BarButtonItem x:Name="bbiDelete" Content="Delete" Glyph="{dx:DXImage Image=Remove_32x32.png}" LargeGlyph="{dx:DXImage Image=Remove_32x32.png}"/>
</dxr:RibbonPageGroup>
</dxr:RibbonPage>
<dxr:RibbonPage x:Name="pageSecurity" Caption="Security">
<dxr:RibbonPageGroup x:Name="rpgUsersSecurity" Caption="Users Security">
<dxb:BarButtonItem x:Name="bbiUsers" Content="Users" Command="{Binding OpenSearchTabCommand}" CommandParameter="{StaticResource UsersSearch}" LargeGlyph="{dx:DXImage Image=User_32x32.png}" Glyph="{dx:DXImage Image=User_16x16.png}"/>
<dxb:BarButtonItem x:Name="bbiGroups" Content="Groups" Command="{Binding }" LargeGlyph="{dx:DXImage Image=UserGroup_32x32.png}" Glyph="{dx:DXImage Image=UserGroup_16x16.png}"/>
</dxr:RibbonPageGroup>
</dxr:RibbonPage>
<dxr:RibbonPage x:Name="pageReferenceTables" Caption="Reference Tables">
<dxr:RibbonPageGroup x:Name="rpgShippment" Caption="Shippment">
<dxb:BarButtonItem x:Name="bbiVessels" Content="Vessels" LargeGlyph="{dx:DXImage Image=GaugeStyleLinearHorizontal_32x32.png}" Glyph="{dx:DXImage Image=User_16x16.png}"/>
</dxr:RibbonPageGroup>
<dxr:RibbonPageGroup x:Name="rpgGeographic" Caption="Geographic">
<dxb:BarButtonItem x:Name="bbiCountries" Content="Countries" Command="{Binding OpenDetailsTabCommand}" CommandParameter="{StaticResource CountriesDetails}" LargeGlyph="{dx:DXImage Image=Country_32x32.png}" Glyph="{dx:DXImage Image=Country_16x16.png}" />
<dxb:BarButtonItem x:Name="bbiRegions" Content="Regions" LargeGlyph="{dx:DXImage Image=ShapeLabels_32x32.png}" Glyph="{dx:DXImage Image=ShapeLabels_16x16.png}" />
</dxr:RibbonPageGroup>
<dxr:RibbonPageGroup x:Name="rpgOtherTables" Caption="Other">
<dxb:BarButtonItem Content="Applications" LargeGlyph="{dx:DXImage Image=CSharp_32x32.png}" Glyph="{dx:DXImage Image=CSharp_16x16.png}"/>
</dxr:RibbonPageGroup>
</dxr:RibbonPage>
<dxr:RibbonPage Caption="Look & Feel">
<dxr:RibbonPageGroup Caption="Theme">
<dxb:BarEditItem x:Name="bThemes" Content="Current theme">
<dxb:BarEditItem.EditTemplate>
<DataTemplate>
<dxe:ComboBoxEdit HorizontalAlignment="Left" Width="200" Margin="0,1"
IsTextEditable="False"
EditValue="{Binding ApplicationThemeName, Source={x:Static dxthm:GlobalThemeHelper.Instance}}"
ValueMember="Name"
ItemsSource="{Binding Mode=OneWay, Source={x:Static dx:Theme.Themes}}"
NullText="NONE" />
</DataTemplate>
</dxb:BarEditItem.EditTemplate>
</dxb:BarEditItem>
</dxr:RibbonPageGroup>
</dxr:RibbonPage>
</dxr:RibbonDefaultPageCategory>
</dxr:RibbonControl>
<dxr:RibbonStatusBarControl DockPanel.Dock="Bottom">
<dxr:RibbonStatusBarControl.LeftItems>
<dxb:BarStaticItem x:Name="biRow" Content="Row:" ShowBorder="False"/>
<dxb:BarStaticItem x:Name="biRowValue" Content="1"/>
<dxb:BarStaticItem x:Name="biColumn" Content="Column:" ShowBorder="False"/>
<dxb:BarStaticItem x:Name="biColumnValue" Content="1"/>
</dxr:RibbonStatusBarControl.LeftItems>
<dxr:RibbonStatusBarControl.RightItems>
<dxb:BarCheckItem x:Name="biLeft" Glyph="{dx:DXImage Image=AlignLeft_16x16.png}" GroupIndex="1" IsChecked="True"/>
<dxb:BarCheckItem x:Name="biCenter" Glyph="{dx:DXImage Image=AlignCenter_16x16.png}" GroupIndex="1"/>
<dxb:BarCheckItem x:Name="biRight" Glyph="{dx:DXImage Image=AlignRight_16x16.png}" GroupIndex="1"/>
</dxr:RibbonStatusBarControl.RightItems>
</dxr:RibbonStatusBarControl>
<Grid>
<dxdo:DockLayoutManager x:Name="dockManager">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ShowingDockHints">
<cmd:EventToCommand
Command="{Binding ShowingDockHintsCommand}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
<dxdo:LayoutGroup>
<dxdo:DocumentGroup x:Name="documentGroupTabs" CaptionLocation="Bottom" ItemsSource="{Binding Tabs}" SelectedTabIndex="{Binding SelectedTabIndex}" DestroyOnClosingChildren="False">
<dxdo:DocumentGroup.Resources>
<Style TargetType="cc:SearchTab">
<Setter Property="CloseCommand" Value="{Binding CloseTabCommand}"/>
<Setter Property="CaptionImage" Value="{dx:DXImage Image=Lookup&Reference_16x16.png}"/>
</Style>
<Style TargetType="cc:DetailsTab">
<Setter Property="CloseCommand" Value="{Binding CloseTabCommand}"/>
<Setter Property="CaptionImage" Value="{dx:DXImage Image=Information_16x16.png}"/>
</Style>
</dxdo:DocumentGroup.Resources>
</dxdo:DocumentGroup>
</dxdo:LayoutGroup>
</dxdo:DockLayoutManager>
</Grid>
</DockPanel>
</Grid>
И класс viewmodel:
public class MainViewModel : ViewModelBase
{
private ObservableCollection<ITab> _tabs;
public ObservableCollection<ITab> Tabs
{
get { return _tabs; }
set { Set(() => Tabs, ref _tabs, value); }
}
private int _selectedTabIndex;
public int SelectedTabIndex
{
get { return _selectedTabIndex; }
set { Set(() => SelectedTabIndex, ref _selectedTabIndex, value); }
}
private ObservableCollection<RibbonPage> _pages;
public ObservableCollection<RibbonPage> Pages
{
get { return _pages; }
set { Set(() => Pages, ref _pages, value); }
}
private RibbonPage _selectedPage;
public RibbonPage SelectedPage
{
get { return _selectedPage; }
set { Set(() => SelectedPage, ref _selectedPage, value); }
}
public ICommand OpenSearchTabCommand { get; set; }
public ICommand OpenDetailsTabCommand { get; set; }
public ICommand CloseTabCommand { get; set; }
public ICommand ShowingDockHintsCommand { get; set; }
public MainViewModel()
{
Tabs = new ObservableCollection<ITab>();
OpenSearchTabCommand = new RelayCommand<UserControl>(content => OpenTab<SearchTab>(content));
OpenDetailsTabCommand = new RelayCommand<UserControl>(content => OpenTab<DetailsTab>(content));
ShowingDockHintsCommand = new RelayCommand<ShowingDockHintsEventArgs>(e => OnShowingDockHints(e));
CloseTabCommand = new RelayCommand<ITab>(tab => CloseTab(tab));
}
private void OnShowingDockHints(ShowingDockHintsEventArgs e)
{
e.DisableAll();
foreach (DockGuide guide in Enum.GetValues(typeof(DockGuide)))
{
if (guide != DockGuide.Bottom)
e.Hide(guide);
}
}
private void OpenTab<T>(UserControl view) where T : ITab, new()
{
Tabs.Add(new T() { Caption = view.GetType().Name + new Random().Next().ToString(), Content = view });
SelectedTabIndex = Tabs.Count - 1;
}
private void CloseTab(ITab tab)
=> Tabs.Remove(tab);
}
1 ответ
Поскольку у вас нет свойства параметра команды для привязки, единственное решение, которое я могу придумать, заключается в следующем:
Пропустите параметр и вместо этого свяжите выбранную вкладку со свойством в модели представления. Затем, когда команда вызывается, вы получаете экземпляр вкладки из этого свойства вместо параметра команды.