2015-09-09 45 views
1

我有一个WPF窗口,其中包含带有两个选项卡的<TabControl>如果容器足够宽,展开TabControl

每个标签主体包含一个UserControl,每个UserControl的固定宽度为300px。

如果WPF窗口超过700像素宽,我要显示的TabControl的页面并排侧,像这样:

如果window.Width
<Window> 
    <TabControl> 
     <TabItem Header="Left page"> 
      <UserControlLeft Width="300" /> 
     </TabItem> 
     <TabItem Header="Right page"> 
      <UserControlRight Width="300" /> 
     </TabItem> 
    </TabControl> 
</Window> 
如果window.Width > = 700
<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition /> 
     <ColumnDefinition Width="50" /> <!-- Spacer column --> 
     <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto" /> 
     <RowDefinition /> 
    </Grid.RowDefinitions> 

    <Label Grid.Column="0" Grid.Row="0" Content="Left page" /> 
    <UserControlLeft Grid.Column="0" Grid.Row="1" Width="300" /> 

    <Label Grid.Column="1" Grid.Row="0" Content="Right page" /> 
    <UserControlRightt Grid.Column="1" Grid.Row="1" Width="300" /> 
</Grid> 

我该如何做到这一点?

我猜我可以在XAML中创建网格和TabControl,并订阅调整大小事件并重新提交UserControlLeftUserControlRight实例,但感觉有点ha and和脆弱。 WPF/XAML有什么等同于CSS的媒体查询?

+0

嘿,那里,给定的解决方案工作? – almulo

+0

@almulo我还没有机会尝试它,谢谢 – Dai

回答

0

您可以定义两个数据模板,每个模板用于不同的布局之一,并使用触发器来选择应用于Window的哪一个。

事情是这样的:

<Window.Resources> 
    <DataTemplate x:Key="SideBySideTemplate"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition /> 
      </Grid.ColumnDefinitions> 

      <local:UserControl1 Grid.Column="0" /> 
      <local:UserControl2 Grid.Column="1" /> 
     </Grid> 
    </DataTemplate> 

    <DataTemplate x:Key="TabControlTemplate"> 
     <TabControl> 
      <TabItem Header="One"> 
       <local:UserControl1 /> 
      </TabItem> 
      <TabItem Header="Two"> 
       <local:UserControl2 /> 
      </TabItem> 
     </TabControl> 
    </DataTemplate> 

    <local:RangeToBooleanConverter x:Key="LesserThan300Converter" 
            LesserThan="300" /> 
</Window.Resources> 
<Window.Style> 
    <Style TargetType="Window"> 
     <Setter Property="ContentTemplate" Value="{StaticResource SideBySideTemplate}" /> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding ActualWidth, RelativeSource={RelativeSource Mode=Self}, Converter={StaticResource LesserThan300Converter}}" 
         Value="True"> 
       <Setter Property="ContentTemplate" Value="{StaticResource TabControlTemplate}" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</Window.Style> 

我用一个自定义的转换器来检查宽度,如果你想使用它,它是这样的:

public class RangeToBooleanConverter : IValueConverter 
{ 
    public double? LesserThan { get; set; } 
    public double? GreaterThan { get; set; } 

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var number = System.Convert.ToDouble(value); 

     return (!LesserThan.HasValue || number < LesserThan.Value) && (!GreaterThan.HasValue || number > GreaterThan.Value); 
    } 

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

注意事项:

  • 这是改变整个ContentTemplateWindow我自行宣布。如果您希望Window具有更多不需要更改的元素,请将此逻辑应用于Window内部的ContentControl
  • 由于整个模板是变化的,在模板中的控件的电流不绑定状态将在每次它改变时间损失,包括键盘焦点等

您可以使用自定义ItemsControl做同样的事情,不要失去控件的状态,只需要改变ItemsPanel或类似的东西......但它比这个解决方案少得多。告诉我你是否需要保持专注或类似的东西,我会研究它。