2012-03-01 24 views
0

我知道這裏有很多關於wpf可視化繼承的問題,但是我找不到與我需要的非常接近的問題。 在一個CRUD應用程序中,我有許多視圖(實際上它們是用戶控件),它們的大多數組件是相同的。我有一個多行和多列網格填充標籤,文本框和其他控件。例如,我們將重點放在第2行和第2列的單元格上。根據用戶正在執行的CRUD操作,它可以包含標籤,文本框,組合框或空的。我在這個網站上學習了其他答案,如何使用樣式和觸發器爲閱讀操作創建一個文本框,但在我的情況下,我必須更改控件類型。當然,我可以重疊我需要的所有控件並改變其可見性,但我不認爲這是最好的方法。 用不同的話來說,我有一些視圖共享用於佈局的網格大部分單元格,但它們對於特定和有限單元格內的某些組件有所不同。 你會在這種情況下做什麼?在贏的形式中,我可以將公共部分放在基類中並從中派生出來,使用xaml我無法做到這一點。我的特殊wpf可視化繼承需要

感謝 菲利波

回答

1

好的,從您的意見我收集,你希望每個上下文有自己的XAML文件,但它是指一些常見的模板。那麼你可以如下:

設置通用模板,例如在CommonControl中。XAML:

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*"/> 
     <RowDefinition Height="*"/> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="*"/> 
     <ColumnDefinition Width="*"/> 
    </Grid.ColumnDefinitions> 
    <Rectangle Grid.Row="0" Grid.Column="0" Fill="Yellow" /> 
    <TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="15" Text="This is some fixed text"/> 
    <ComboBox Grid.Row="0" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
    <StackPanel Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center"> 
     <CheckBox>My first checkbox</CheckBox> 
     <CheckBox>My second checkbox</CheckBox> 
    </StackPanel> 
    <ContentControl Grid.Row="1" Grid.Column="1" Content="{Binding Path=SpecificPart1, RelativeSource={RelativeSource AncestorType=UserControl}}"/> 
    <Ellipse Grid.Row="1" Grid.Column="2" Fill="Blue"/> 
</Grid> 

這具有在形成網格的所有位置的公共UI的各種UI元素,除了網格行1,列1(下部中心窗格)中,其中上下文特定UI將被顯示。

代碼

現在的背後,CommonControl.xaml.cs,你設置的依賴對象,使上下文中的具體UI被送入模板:

public object SpecificPart1 
    { 
    get { return this.GetValue(SpecificPart1Property); } 
    set { this.SetValue(SpecificPart1Property, value); } 
    } 
    public static readonly DependencyProperty SpecificPart1Property = DependencyProperty.Register(
     "SpecificPart1", typeof(object), typeof(CommonControl), new PropertyMetadata(false)); 

如果有一個以上的位置您希望放置特定於上下文的用戶界面,然後您可以在此處爲其他部分添加另一個依賴項屬性。

然後,您可以設置許多其他XAML文件,只要您喜歡,這些文件都會引用此內容並插入它們自己的UI以進入不同的部分。下面是一個例子,其中提供了一些綠色的斜體文字。在MySpecificControl.xaml中:

<my:CommonControl> 
     <my:CommonControl.SpecificPart1> 
      <TextBlock Foreground="DarkGreen" FontStyle="Italic" FontSize="14">This is my context specific UI</TextBlock> 
     </my:CommonControl.SpecificPart1> 
    </my:CommonControl> 
0

這聽起來像你想使用觸發器一個ContentControl中。我不知道究竟是什麼決定了你希望顯示哪種類型的控件,但是例如說你有一個屬性「Condition」,它可以取值「ConditionValue1」或「ConditionValue2」,並且你希望顯示一個不同的UI依賴項上重視它,你可以使用XAML這樣的:

<ContentControl Grid.Row="2" Grid.Column="2"> 
     <ContentControl.Style> 
      <Style> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding Condition}" Value="ConditionValue1"> 
         <Setter Property="ContentControl.Template"> 
          <Setter.Value> 
           <ControlTemplate> 
            [ First control goes here ] 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </DataTrigger> 
        <DataTrigger Binding="{Binding Condition}" Value="ConditionValue2"> 
         <Setter Property="ContentControl.Template"> 
          <Setter.Value> 
           <ControlTemplate> 
            [ Second control goes here ] 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </ContentControl.Style> 
    </ContentControl> 

的這種過度使用可視化的一大優勢是,當不同的是到位的控件只在需要的時候加載,並且,舊的可以自由卸載。當Visibility = Collapsed時,控件仍然被加載並掛在背景中。

0

那麼,我一定會考慮DataTemplates

如果需求足夠簡單,只需根據DataType選擇一個模板,那麼您就全都設置了......例如,以下是一些XAML,如果您有,它將自動使用正確的模板(TextBox或DatePicker)一組stringDateTime的對象集合。

<MyControl.Resources> 
    <DataTemplate DataType="{sys:String}"> 
    <TextBox Text="{Binding}" /> 
    </DataTemplate> 

    <DataTemplate DataType="{sys:DateTime}"> 
    <DatePicker Date="{Binding}" /> 
    </DataTemplate> 
</MyControl.Resources> 

<ItemsControl Items="{Binding MyListOfObjects}" /> 

如果需要簡單的類型之外的其他邏輯,那麼你將要尋找到一個DataTemplateSelector。例如,如果您擁有複雜對象的集合以及那些將決定選擇哪個DataTemplate的複雜對象中的某些屬性,那麼您應該使用DataTemplateSelector

<MyControl.Resources> 
    <DataTemplate x:Key="TextViewTemplate"> 
    <StackPanel Orientation="Horizontal"> 
     <Label Content="Name:" /> 
     <TextBox Text="{Binding Path=Name}" /> 
    </StackPanel> 
    </DataTemplate> 

    <DataTemplate x:Key="TextUpdateTemplate"> 
    <StackPanel Orientation="Horizontal"> 
     <Label Content="Name:" /> 
     <TextBox Text="{Binding Path=Name}" IsReadOnly="True" /> 
    </StackPanel> 
    </DataTemplate> 

    <local:MyDataTemplateSelector x:Key="MySelector" 
    ManagerTemplate="{StaticResource TextUpdateTemplate}" 
    EmployeeTemplate="{StaticResource TextViewTemplate}" /> 
</MyControl.Resources> 

<ItemsControl Items="{Binding Employees}" 
       ItemTemplateSelector="{StaticResource MySelector}" /> 


public MyDataTemplateSelector : DataTemplateSelector 
{ 
    public DataTemplate ManagerTemplate { get; set; } 
    public DataTemplate EmployeeTempalte { get; set; } 

    public override DataTemplate SelectTemplate(object item, 
     DependencyObject container) 
    { 
     switch (UserClass.UserLevel) 
     { 
      case UserLevel.Manager: 
       if (ManagerTemplate != null) 
        return ManagerTemplate; 
       break; 

      case UserLevel.Employee: 
       if (EmployeeTemplate != null) 
        return EmployeeTemplate; 
       break; 

      default: 
       throw InvalidOperationException("Invalid enumeration value."); 
     } 

     return base.SelectTemplate(item, container); 
    } 
} 

請記住,這是做這個只是其中一種方法... DataTemplateSelector s的很少使用,因爲有很多的選擇邏輯可以簡單地適用於類似的模板和露出一個附加屬性。例如,不使用此選擇器,您可以簡單地公開一個「IsEditable」屬性並將其綁定到IsReadOnly DependencyProperty。但是,這只是一個例子來顯示使用情況。無論如何,希望有所幫助。

+0

對不起,但我不明白你的解決方案。它的共同控制在哪裏?我在尋找的是一種方式來編寫所有我的視圖所使用的所有控件(可能在一個模板中),然後爲每個用例指定多個視圖,其中我只指定要添加的基本模板。有沒有簡單的方法來實現這一目標? – Filippo 2012-03-01 15:24:06

+0

也許我誤解了你的問題。你能更清楚一點嗎?因爲就目前而言,你對我的回答感到困惑的是我對你的評論感到困惑。 – 2012-03-01 17:36:19

+0

在MVVM場景中,我有和想要閱讀的視圖,一個用於編輯,一個用於創建,另一個用於創建特殊情況,ecc。所有這些觀點都分享了他們大部分的組成部分,只有很小的差異:我可以在哪裏放置通用部分?我不想要一個適應CRUD操作的獨特xaml文件,我想要更多的xaml文件,它以某種方式從另一個xaml文件「繼承」公共組件。可能是模板是正確的答案,但我需要遵循一些示例。 – Filippo 2012-03-02 08:43:32