将孩子锚定到父母控制

时间:2011-03-18 22:57:21

标签: wpf xaml

我是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 个答案:

答案 0 :(得分:2)

您已将StackPanel指定为ItemsPanelTemplate。 StackPanel具有每个孩子将从前一个孩子旁边开始的语义,并且相对于该位置将应用边距。

如果将ItemsPanelTemplate更改为练习相对定位的面板,则每个子项将从相同位置开始,然后将相对于该位置应用边距。可能最简单的方法是使用Canvas作为ItemsPanelTemplate。然后每个项目将从(0,0)开始,您的保证金将其偏移到所需的位置。

有一个使用Canvas将项目定位在由http://www.mindscapehq.com/blog/index.php/2007/12/04/five-steps-to-wpf-data-visualisation/的项目数据确定的绝对位置的示例(向下滚动到步骤4)。该示例使用ItemContainerStyle而不是Margin进行定位,但如果您更喜欢Margin,那么它应该很容易适应。

答案 1 :(得分:0)

使用Canvas而不是使用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>