如何在通用组合框

时间:2018-04-16 13:17:45

标签: c# wpf mvvm

我想要一个像这样的组合框:

enter image description here

但是在代码中没有办法做到这一点。我正在使用MVVM模式。所以我有一个观点:

<ComboBox Style="{StaticResource ComboStyle}" ItemsSource="{Binding ResultObjects}" SelectedItem="{Binding SelectedObject,Mode=TwoWay}" />

和ViewModel:

public IEnumerable<DateTime> ResultObjects { get;set; }
public DateTime SelectedObject{ get;set; }

事实是-All-和-custom-不是DateTime。它不能添加到此列表中。 我记得在MVC中我们有一个“Dropdown helper”。

我在MVVM中可以做什么?

3 个答案:

答案 0 :(得分:2)

您可以绑定到IEnumerable<KeyValuePair<DateTime?, string>>,其中键表示实际值,值表示该值的自定义字符串表示形式:

public IEnumerable<KeyValuePair<DateTime?, string>> ResultObjects { get; set; }
public DateTime? SelectedObject { get; set; }

...

ResultObjects = new List<KeyValuePair<DateTime?, string>>()
{
    new KeyValuePair<DateTime?, string>(null, "All"),
    new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), new DateTime(2018,04,17).ToString("yyyy/MM/dd")),
    new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), new DateTime(2018,04,17).ToString("yyyy/MM/dd @ HH:mm:ss")),
    new KeyValuePair<DateTime?, string>(new DateTime(2018,04,17), "Custom...")
};
...

<强> XAML:

<ComboBox 
    ItemsSource="{Binding ResultObjects}" 
    SelectedValue="{Binding SelectedObject}"
    DisplayMemberPath="Value"
    SelectedValuePath="Key"/>

如果您希望能够代表其他类型的值,那么除非DateTime中的实际IEnumerable<DateTime>值,否则您无法返回任何内容,而应该更改源集合的类型。

答案 1 :(得分:1)

我处理此问题的方法是定义ObservableCollection<object> 当wpf遇到呈现给ui的对象时,它首先会查看它是否为该事物定义了模板。如果它没有,它将在对象上使用ToString。对于简单的情况,您可以依赖它,并在您要使用的任何对象上覆盖.ToString() 如果您想要更复杂的显示而不仅仅是字符串,那么您可以根据数据类型定义一个以对象为目标的数据窗口。
一个可以派上用场的伎俩 您甚至可以从一个基础对象继承并为其定义模板,然后为子类型定义更具体的模板。从您的基础对象继承的子类型将由您的&#34;默认&#34;处理。

EG。
我有一个地图编辑器。用户正在从他将要绘制的不同地形中进行选择。我想为这些显示不同的东西。我有一个BaseTerrainVM,然后我继承了河流,轮廓,树林等。 这是我用来模板列表框中项目的标记的子集:

<ListBox.Resources>
    <DataTemplate DataType="{x:Type local:BaseTerrainVM}">
        <Grid>
            <TextBlock Text="{Binding DisplayType}" HorizontalAlignment="Left"
                       VerticalAlignment="Center"/>
            <TextBlock Text="{Binding ID}" 
                       HorizontalAlignment="Right"
                       VerticalAlignment="Center"/>
        </Grid>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:ContourVM}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2*"/>
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding DisplayType}" 
                       Grid.Column="0"
                       VerticalAlignment="Center"/>
            <StackPanel Orientation="Horizontal"
                        Grid.Column="1"
                        TextElement.FontFamily="Century Gothic"
                        TextElement.FontSize="{DynamicResource LargeFont}"
                        TextElement.FontWeight="Normal"
                        >
                <TextBox MinWidth="50"
                         Text="{Binding Height}"
                         GotKeyboardFocus="TextBox_GotKeyboardFocus"
                         >
                    <i:Interaction.Behaviors>
                        <ui:TextBoxDecimalRangeBehaviour MaxDecimals="0" 
                                         MaxInteger="3" 
                                         Minimum="{StaticResource Zero}" 
                                         Maximum="{StaticResource TwoFiveFive}" />
                        <ui:SelectAllTextBoxBehavior/>
                    </i:Interaction.Behaviors>
                </TextBox>
                <TextBlock Text="units"
                           Margin="2,0,0,0"
                           ToolTip="Elevation is represented by a number 0-255 which is multiplied by a factor to give metres"
                              />
            </StackPanel>
            <TextBlock Text="{Binding ID}" 
                       Grid.Column="2"
                       VerticalAlignment="Center"
                       />
        </Grid>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:RiverVM}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2*"/>
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding DisplayType}" 
                       Grid.Column="0"
                       VerticalAlignment="Center"/>
            <StackPanel Orientation="Horizontal"
                        Grid.Column="1"
                        TextElement.FontFamily="Century Gothic"
                        TextElement.FontSize="{DynamicResource LargeFont}"
                        TextElement.FontWeight="Normal"
                        >
                <Button 
                        Command="{Binding PressureFromStartCommand}"
                        Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                        Height="20"
                        ToolTip="Widen from Start of stroke"
                        >
                        <Path Data="{StaticResource FlowRight}"
                          Stretch="Uniform"
                          Fill="LightBlue"
                          Stroke="DodgerBlue"
                          StrokeThickness="1"
                          />
                </Button>
                <Button 
                        Command="{Binding PressureConstantCommand}"
                        Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                        Height="20"
                        ToolTip="Constant width for river"
                        >
                    <Rectangle
                          Width="18"
                          Height="6"
                          Fill="LightBlue"
                          Stroke="DodgerBlue"
                          StrokeThickness="1"
                          />
                </Button>
                <Button 
                        Command="{Binding PressureFromEndCommand}"
                        Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                        Height="20"
                        ToolTip="Widen from End of stroke"
                        >
                    <Path Data="{StaticResource FlowRight}"
                          Stretch="Uniform"
                          Fill="LightBlue"
                          Stroke="DodgerBlue"
                          StrokeThickness="1"
                          RenderTransformOrigin="0.5,0.5"
                          >
                        <Path.RenderTransform>
                            <ScaleTransform ScaleX="-1" ScaleY="1" />
                        </Path.RenderTransform>
                    </Path>
                </Button>
            </StackPanel>
            <TextBlock Text="{Binding ID}" 
                       Grid.Column="2"
                       VerticalAlignment="Center"
                       />
        </Grid>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:BoundaryVM}">
        <Grid>

(这可能会让泥浆变得有趣。)
我展示这些的Terrains实际上是一个复合系列。在我的情况下,这是因为我将地图上的所有水转化为一个物体,因此在一条道路与下一条道路之间没有边界,或者湖泊和河流流入其中。我需要提出水的两种表示形式,但要在它们之间切换。

答案 2 :(得分:0)

您需要使用CompositeCollection,它可以处理多个集合和其他对象。

尝试这样的事情

<ComboBox>
    <ComboBox.ItemsSource>
        <CompositeCollection>
            <ComboBoxItem Content="--All--" />
            <CollectionContainer Collection="{Binding Source=ResultObjects}" />
            <ComboBoxItem Content="--Custom--" />
        </CompositeCollection>
    </ComboBox.ItemsSource>
</ComboBox>