2011-03-18 50 views
0

我是WPF的新手,我想設置孩子相對於父控件的邊距,而不是樹中的前一個孩子。我正在使用IValueConverter來轉換邊距。將孩子鎖定到父控件

<Grid Background="#668" Margin="1"> 
      <StackPanel Grid.Row="1" Orientation="Horizontal"> 
       <ItemsControl ItemsSource="{Binding KeyFrames}" > 
        <ItemsControl.ItemTemplate> 
         <DataTemplate> 
         <Button Width="{Binding Path=ScaledLength}" HorizontalAlignment="Left" 
             Margin="{Binding Path=ScaledStartOffset, Converter={StaticResource ClipLeftMarginConverter} }"> 
         </Button> 
         </DataTemplate> 
        </ItemsControl.ItemTemplate> 
        <ItemsControl.ItemsPanel> 
         <ItemsPanelTemplate> 
          <StackPanel Orientation="Horizontal"/> 
         </ItemsPanelTemplate> 
        </ItemsControl.ItemsPanel> 
       </ItemsControl> 
      </StackPanel> 
     </Grid> 

我的IValueConverter是

public class ClipRegionMarginConverter : DependencyObject, IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     double inputValue = (double)value; 
     return new Thickness(inputValue, 0, 0, 0); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new Exception("The method or operation is not implemented."); 
    } 
} 

我想知道如果有一個不同的控制,我可以使用,使得按鈕保證金是相對於網格而不是一個按鈕。或者,如果您發現我可以對IValueConverter進行更改,以解決同樣的問題,那我也很好。

回答

2

您已將StackPanel指定爲ItemsPanelTemplate。 StackPanel有一個語義,每個孩子將從前一個孩子旁邊開始,並且該邊距將被應用於該位置。

如果您將ItemsPanelTemplate更改爲面板不是練習相對定位,那麼每個孩子將從相同的位置開始,然後將相對於該位置應用邊距。可能最簡單的方法是使用Canvas作爲ItemsPanelTemplate。然後每個項目將從(0,0)開始,您的保證金將其抵消到期望的位置。

有一個使用畫布定位項目的例子,該項目位於由項目數據確定的絕對位置,位於http://www.mindscapehq.com/blog/index.php/2007/12/04/five-steps-to-wpf-data-visualisation/(向下滾動到步驟4)。該示例使用ItemContainerStyle而不是Margin進行定位,但如果您更喜歡Margin,則應該很容易適應。

0

而不是使用StackPanel,使用畫布。這可能會解決您的問題。正如itowlson所說,Canvas開始讓孩子們保持在0,0。所以,無論你給元素的邊距是多少,這都與畫布有關。而不是前一個元素。

以下代碼可能會對您有所幫助。

public partial class MainWindow : Window 
{ 
    public ObservableCollection<Person> Persons { get; set; } 
    public MainWindow() 
    { 
     InitializeComponent(); 

     Persons = new ObservableCollection<Person>(); 
     Persons.Add(new Person("one", 100)); 
     Persons.Add(new Person("two", 200)); 
     Persons.Add(new Person("three", 300)); 
     Persons.Add(new Person("four", 400)); 

     DataContext = this; 
    } 
} 

public class Person 
{ 
    public String Name { get; set; } 
    public Thickness Age { get; set; } 

    public Person(string name, int age) 
    { 
     this.Name = name; 
     this.Age = new Thickness(age, 0, 0, 0); 
    } 
} 


<Grid Background="#668" Margin="1"> 
     <ItemsControl ItemsSource="{Binding Persons}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <TextBlock Text="{Binding Name}" Margin="{Binding Age}"/> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <Canvas/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
     </ItemsControl> 
</Grid>