2011-09-18 28 views
1

我有一個數據網格綁定到自定義「模型」類的列表。 在其中一個單元格中,我有4個矩形,代表模型類的4個不同的字符串屬性。分解數據觸發器的代碼綁定到不同的屬性

如果相應屬性爲空,則矩形應該是黑色,否則爲紅色。 我在每個矩形上使用DataTrigger實現了這一點,並且它工作正常,但我必須在四次綁定路徑更改的情況下寫入相同的數據觸發器。看起來它可能更有效率。

是否有一種巧妙的方式來定義一個DataTrigger一次,併爲它應用於每個元素(在我的情況下矩形)使用不同的綁定路徑?

謝謝。

這是我的模型類:

class myModel 
{ 
    [...] 
    public string pr1 { get; set; } 
    public string pr2 { get; set; } 
    public string pr3 { get; set; } 
    public string pr4 { get; set; } 
    [...] 
} 

這是綁定到一個List<myModel>數據網格:

<DataGrid AutoGenerateColumns="False" Height="200" Name="myDg" ItemsSource="{Binding}"> 
    <DataGrid.Columns> 
     [...] 
     <DataGridTemplateColumn Header="prs"> 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <StackPanel Name="spRow" Orientation="Horizontal"> 
         <Rectangle Height="15" Name="rPr1" Width="10"> 
          <Rectangle.Style> 
           <Style TargetType="{x:Type Rectangle}"> 
            <Setter Property="Rectangle.Stroke" Value="Red"/> 
            <Style.Triggers> 
             <DataTrigger Binding="{Binding Path=pr1}" Value=""> 
              <Setter Property="Rectangle.Stroke" Value="Black"/> 
             </DataTrigger> 
            </Style.Triggers> 
           </Style> 
          </Rectangle.Style> 
         </Rectangle> 
         <Rectangle Height="15" Name="rPr2" Width="10"> 
          <Rectangle.Style> 
           <Style TargetType="{x:Type Rectangle}"> 
            <Setter Property="Rectangle.Stroke" Value="Red"/> 
            <Style.Triggers> 
             <DataTrigger Binding="{Binding Path=pr2}" Value=""> 
              <Setter Property="Rectangle.Stroke" Value="Black"/> 
             </DataTrigger> 
            </Style.Triggers> 
           </Style> 
          </Rectangle.Style> 
         </Rectangle> 
         <Rectangle Height="15" Name="rPr3" Width="10"> 
          <Rectangle.Style> 
           <Style TargetType="{x:Type Rectangle}"> 
            <Setter Property="Rectangle.Stroke" Value="Red"/> 
            <Style.Triggers> 
             <DataTrigger Binding="{Binding Path=pr3}" Value=""> 
              <Setter Property="Rectangle.Stroke" Value="Black"/> 
             </DataTrigger> 
            </Style.Triggers> 
           </Style> 
          </Rectangle.Style> 
         </Rectangle> 
         <Rectangle Height="15" Name="rPr4" Width="10"> 
          <Rectangle.Style> 
           <Style TargetType="{x:Type Rectangle}"> 
            <Setter Property="Rectangle.Stroke" Value="Red"/> 
            <Style.Triggers> 
             <DataTrigger Binding="{Binding Path=pr4}" Value=""> 
              <Setter Property="Rectangle.Stroke" Value="Black"/> 
             </DataTrigger> 
            </Style.Triggers> 
           </Style> 
          </Rectangle.Style> 
         </Rectangle> 
        </StackPanel> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
    </DataGrid.Columns> 
</DataGrid> 

回答

1

有兩種方法...

解決方案1:

您可以在祖先層次概括樣式,然後專注於每個長方形的模型屬性。

您可以這樣做的方法是將每個矩形的具體pr屬性標記爲Tag,然後使用Tag作爲通用數據觸發源。

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <StackPanel Grid.Row="0" Orientation="Horizontal"> 
     <TextBox Margin="5" x:Name="MyTextBox1" Text="pr1" /> 
     <TextBox Margin="5" x:Name="MyTextBox2" Text="pr2" /> 
     <TextBox Margin="5" x:Name="MyTextBox3" Text="pr3" /> 
     <TextBox Margin="5" x:Name="MyTextBox4" Text="pr4" /> 
    </StackPanel> 
    <StackPanel Grid.Row="1" Orientation="Horizontal"> 
     <StackPanel.Resources> 
      <Style TargetType="{x:Type Rectangle}"> 
       <Setter Property="Height" Value="20"/> 
       <Setter Property="Width" Value="20"/> 
       <Setter Property="Stroke" Value="Black"/> 
       <Setter Property="StrokeThickness" Value="1"/> 
       <Setter Property="Margin" Value="5"/> 
       <Style.Triggers> 
        <DataTrigger 
          Binding="{Binding Tag, 
           RelativeSource={RelativeSource Self}}" 
          Value=""> 
         <Setter Property="Fill" Value="Red"/> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </StackPanel.Resources> 
     <Rectangle Tag="{Binding Text, ElementName=MyTextBox1, Mode=OneWay}" /> 
     <Rectangle Tag="{Binding Text, ElementName=MyTextBox2, Mode=OneWay}" /> 
     <Rectangle Tag="{Binding Text, ElementName=MyTextBox3, Mode=OneWay}" /> 
     <Rectangle Tag="{Binding Text, ElementName=MyTextBox4, Mode=OneWay}" /> 
    </StackPanel> 
</Grid> 

所以在上面的例子中,當你清除單個文本框時,你會得到一個相應的紅色矩形。請注意,我們使用標籤通過DataTrigger但我們也可以使用正常的觸發器...

<Trigger Property="Tag" Value=""> 
    <Setter Property="Fill" Value="Red"/> 
</Trigger> 

解決方案2:

使用ItemsControl,然後在模型4(或n)項目保持pr1..pr4的值。

編輯

....

更改您模式,包括pr對象的列表。我正在使用SourceFilter只是爲了容納屬性pr'n'擁有的雙向可編輯字符串值...您可以使用任何通過屬性保存字符串值的類。

public List<SourceFilter> pr 
    { 
     get; 
     set; 
    } 

然後我加載四個屬性四個SourceFilter對象...

pr = new List<SourceFilter>(); 
    pr.Add(new SourceFilter("pr1")); 
    pr.Add(new SourceFilter("pr2")); 
    pr.Add(new SourceFilter("pr3")); 
    pr.Add(new SourceFilter("pr4")); 

然後我用的ItemsControl的ItemPanelItemsTemplateItemsSource從第1步精確達到同樣的效果......

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <ItemsControl Grid.Row="0" ItemsSource="{Binding pr, ElementName=MyWindow2}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" IsItemsHost="True"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <TextBox Margin="5" 
         Text="{Binding Path=Source, 
             Mode=TwoWay, 
             UpdateSourceTrigger=PropertyChanged}"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
    <ItemsControl Grid.Row="1" ItemsSource="{Binding pr, ElementName=MyWindow2}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal" IsItemsHost="True"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <DataTemplate.Resources> 
        <Style TargetType="{x:Type Rectangle}"> 
         <Setter Property="Height" Value="20"/> 
         <Setter Property="Width" Value="20"/> 
         <Setter Property="Stroke" Value="Black"/> 
         <Setter Property="StrokeThickness" Value="1"/> 
         <Setter Property="Margin" Value="5"/> 
         <Style.Triggers> 
          <DataTrigger Binding="{Binding Source}" Value=""> 
           <Setter Property="Fill" Value="Red"/> 
          </DataTrigger> 
         </Style.Triggers> 
        </Style> 
       </DataTemplate.Resources> 
       <Rectangle /> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

好處是你不必在任何地方指定特定的pr1..pr4綁定。加上它的可擴展性(因爲pr可以容納任何n值,並會自動生成相同數量的矩形)。

+0

嘗試了你的第一個解決方案,它效果很好。如果矩形的數量可以在運行時改變,那麼第二個可能會很方便。謝謝。 –

1

是的,你可以創建一個從DataTrigger派生的類和具有不變的細節預-set:

public class RedBlackDataTrigger : DataTrigger 
    { 
    public RedBlackDataTrigger() 
    { 
     Value = string.Empty; 
     Setters.Add(new Setter(Rectangle.StrokeProperty, new SolidColorBrush(Colors.Black))); 
    } 
    } 

您可以在XAML中使用它,只需添加綁定:

<Rectangle Height="15" Width="10"> 
    <Rectangle.Style> 
     <Style TargetType ="Rectangle"> 
      <Setter Property="Rectangle.Stroke" Value="Red"/> 
      <Style.Triggers> 
       <Your-Namespace:RedBlackDataTrigger Binding="{Binding Path=pr4}" /> 
      </Style.Triggers> 
     </Style> 
    </Rectangle.Style> 
    </Rectangle> 

既然你也複製你的Style,你可以把它更進一步,創建一個派生樣式類:

public class RectangleStyle : Style 
    { 
    public RectangleStyle() 
    { 
     TargetType = typeof (Rectangle); 
     Setters.Add(new Setter(Rectangle.StrokeProperty, new SolidColorBrush(Colors.Red))); 
    } 

    public string ColorTrigger 
    { 
     set 
     { 
     Triggers.Add(new RedBlackDataTrigger {Binding = new Binding(value) }); 
     } 
    } 
    } 

現在你已經減少的事情:

<Rectangle Height="15" Width="10"> 
     <Rectangle.Style> 
      <Your-Namespace:RectangleStyle ColorTrigger="pr4" /> 
     </Rectangle.Style> 
    </Rectangle> 

你甚至可以更進一步,創建派生的Rectangle類來完成這一切。

+0

在這種情況下,angelWPF解決方案更適合我的需求。但我喜歡你的解決方案,並將其用於我的項目的另一部分。謝謝。 –

相關問題