将孩子固定在家长控制之下

发布于 2024-10-24 12:46:24 字数 1794 浏览 0 评论 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 进行更改来解决相同的问题,我也同意。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你丑哭了我 2024-10-31 12:46:24

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

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

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

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.

我乃一代侩神 2024-10-31 12:46:24

不使用 StackPanel,而是使用 Canvas。这可能会解决您的问题。
正如 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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文