2015-09-09 46 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或類似的東西......但它比這個解決方案少得多。告訴我你是否需要保持專注或類似的東西,我會研究它。