开发者

Anchor children to parent control

开发者 https://www.devze.com 2023-02-17 14:45 出处:网络
I\'m new to WPF and I would like to set the margin of children relative to the parent control instead of the previous child in the tree. I\'m using a IValueConverter to convert the margin.

I'm new to WPF and I would like to set the margin of children relative to the parent control instead of the previous child in the tree. I'm using a IValueConverter to convert the margin.

<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>

My IValueConverter is

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.");
    }
}

I am wondering if there is a different control I can use so that the button margin is relative to the Grid and not the previous button. Alternatively if you notice a change I can make to the IValueConverter that would solve the same problem I'm fine with that as well.


You've specified StackPanel as your ItemsPanelTemplate. StackPanel has the semantics that each child will start out next to the previous child, and the margin will be applied relative to that position.

If you change your ItemsPanelTemplate to a panel that doesn't practise relative positioning, then each child will start at the same position, and the margin will then be applied relative to that position. Probably the easiest way to do this is to use a Canvas as your ItemsPanelTemplate. Then each item will start out at (0,0), with your margin offsetting it to the desired location.

There's an example of using a Canvas to position items at an absolute position determined by the item data at http://www.mindscapehq.com/blog/index.php/2007/12/04/five-steps-to-wpf-data-visualisation/ (scroll down to Step 4). The example uses ItemContainerStyle instead of Margin for positioning, but if you prefer Margin then it should be easy to adapt.


Instead of using StackPanel, use Canvas. This might solve your problem. As itowlson said Canvas starts keeping the children at 0,0. So, whatever Margin you gave to the element, that will be relative to the canvas. and not to the previous element.

the following code may be helpful.

    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>
0

精彩评论

暂无评论...
验证码 换一张
取 消