Выбор DataTemplate на основе подтипа объекта

Вот вам решение VBA (я не знаю, как это сделать с помощью Python).

Если вам нужно преобразовать несколько файлов Word в другие форматы, такие как TXT, RTF, HTML или PDF, запустите приведенный ниже скрипт.

Option Explicit On

Sub ChangeDocsToTxtOrRTFOrHTML()
    'with export to PDF in Word 2007
    Dim fs As Object
    Dim oFolder As Object
    Dim tFolder As Object
    Dim oFile As Object
    Dim strDocName As String
    Dim intPos As Integer
    Dim locFolder As String
    Dim fileType As String
    On Error Resume Next

    locFolder = InputBox("Enter the folder path to DOCs", "File Conversion", "C:\Users\your_path_here\")
    Select Case Application.Version
        Case Is < 12
            Do
                fileType = UCase(InputBox("Change DOC to TXT, RTF, HTML", "File Conversion", "TXT"))
            Loop Until (fileType = "TXT" Or fileType = "RTF" Or fileType = "HTML")
        Case Is >= 12
            Do
                fileType = UCase(InputBox("Change DOC to TXT, RTF, HTML or PDF(2007+ only)", "File Conversion", "TXT"))
            Loop Until (fileType = "TXT" Or fileType = "RTF" Or fileType = "HTML" Or fileType = "PDF")
    End Select

    Application.ScreenUpdating = False
    Set fs = CreateObject("Scripting.FileSystemObject")
    Set oFolder = fs.GetFolder(locFolder)
    Set tFolder = fs.CreateFolder(locFolder & "Converted")
    Set tFolder = fs.GetFolder(locFolder & "Converted")

    For Each oFile In oFolder.Files
        Dim d As Document
        Set d = Application.Documents.Open(oFile.Path)
        strDocName = ActiveDocument.Name
        intPos = InStrRev(strDocName, ".")
        strDocName = Left(strDocName, intPos - 1)
        ChangeFileOpenDirectory tFolder
        Select Case fileType
            Case Is = "TXT"
                strDocName = strDocName & ".txt"
                ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatText
        Case Is = "RTF"
                strDocName = strDocName & ".rtf"
                ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatRTF
        Case Is = "HTML"
                strDocName = strDocName & ".html"
                ActiveDocument.SaveAs FileName:=strDocName, FileFormat:=wdFormatFilteredHTML
        Case Is = "PDF"
                strDocName = strDocName & ".pdf"
                ActiveDocument.ExportAsFixedFormat OutputFileName:=strDocName, ExportFormat:=wdExportFormatPDF
        End Select
        d.Close
        ChangeFileOpenDirectory oFolder
    Next oFile
    Application.ScreenUpdating = True

End Sub
11
задан Joe White 26 April 2009 в 18:21
поделиться

3 ответа

I'm not exactly sure what your model looks like, but you can always use a . to bind to an objects property. For example:

<DataTemplate DataType="TerrainModels:Square">
  <StackPanel>
    <TextBlock Content="{Binding Path=Feature.Name}"/>
    <TextBlock Content="{Binding Path=Feature.Type}"/>
  </StackPanel>
</DataTemplate>

Update

Although, if you are looking for a way to bind two different objects in a collection you might want to take a look at the ItemTemplateSelector property.

In your scenario it would be something like this (not tested):

public class TerrainSelector : DataTemplateSelector
{
  public override DataTemplate SelectTemplate(object item, DependencyObject container)
  {
    var square = item as Square;
    if (square == null) 
       return null;
    if (square.Terrain is Dirt)
    {
      return Application.Resources["DirtTemplate"] as DataTemplate;
    }
    if (square.Terrain is Steel)
    {
      return Application.Resources["SteelTemplate"] as DataTemplate;
    }
    return null;
  }
}

Then to use it you would have:

App.xaml

<Application ..>
  <Application.Resources>
    <DataTemplate x:Key="DirtTemplate">
      <!-- template here -->
    </DataTemplate>
    <DataTemplate x:Key="SteelTemplate">
      <!-- template here -->
    </DataTemplate>
  </Application.Resources>
</Application>

Window.xaml

<Window  ..>
  <Window.Resources>
    <local:TerrainSelector x:Key="templateSelector" />
  </Window.Resources>
  <ItemsControl ItemSource="{Binding Path=Terrain}" ItemTemplateSelector="{StaticResource templateSelector}" />
</Window>
10
ответ дан 3 December 2019 в 08:31
поделиться

I'm adding another answer, because this is kind of a different take on the problem then my other answer.

If you are trying to change the background of the Canvas, then you can use a DataTrigger like this:

<DataTemplate DataType="{x:Type WpfApplication1:Square}">
    <DataTemplate.Resources>
        <WpfApplication1:TypeOfConverter x:Key="typeOfConverter" />
    </DataTemplate.Resources>
    <Canvas Name="background" Fill="Green" />
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path="Terrain" Converter={StaticResource typeOfConverter}}" Value="{x:Type WpfApplication1:Dirt}">
            <Setter  TargetName="background"Property="Fill" Value="Tan" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Path="Terrain" Converter={StaticResource typeOfConverter}}" Value="{x:Type WpfApplication1:SteelPlate}">
            <Setter TargetName="background" Property="Fill" Value="Silver" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

You'd also need to use this Converter:

public class TypeOfConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value.GetType();
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new System.NotImplementedException();
    }

}
2
ответ дан 3 December 2019 в 08:31
поделиться

Я полагаю, что лучшее, что вы можете сделать для устранения накладных расходов (и избыточности) визуального дерева, это:

<ItemsControl ItemsSource="{Binding Squares}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding Terrain}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Я мог бы поклясться, что вы могли бы сделать этот шаг дальше, непосредственно назначив ] Свойство Content объекта ContentPresenter , сгенерированного для каждого элемента в ItemsControl :

<ItemsControl ItemsSource="{Binding Squares}">
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="ContentPresenter.Content" Content="{Binding Terrain}"/>
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

Однако, у ContentPresenter , похоже, есть родительский элемент DataContext как его DataContext , а не как квадрат . Это не имеет смысла для меня. Он отлично работает с ListBox или любым другим ItemsControl подклассом. Возможно, это ошибка WPF - не уверен. Я должен буду изучить это далее.

2
ответ дан 3 December 2019 в 08:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: