سؤال

هل هناك أي طريقة تجعل التحكم في علامة التبويب يأخذ حجم أكبر عنصر في علامة التبويب (حسنًا، في الواقع، محتوى عنصر التبويب)؟

نظرًا لعدم تخصيص حجم معين لعنصر التحكم في علامة التبويب، فيجب ضبط حجمه تلقائيًا:يقوم بذلك بشكل صحيح، ولكن عندما تقوم بالتبديل بين علامات التبويب، فإنه يتغير حجمه تلقائيًا إلى ارتفاع (وعرض) محتويات علامة التبويب المحددة حاليًا.

لا أريد أن يتم تغيير الحجم، ودع عنصر التحكم في علامة التبويب يتولى ارتفاع العنصر الأكبر، مع الاستمرار في ضبط حجمه تلقائيًا.

أي أدلة؟لقد حاولت ربط البيانات بـ Height خاصية كل عنصر يستخدم كمحتوى لاستخدام الارتباط المتعدد، مع الارتباطات على كليهما ActualHeight و ال Items خصائص Tabcontrolولكن للأسف، ActualHeight من عناصر المحتوى دائمًا 0.

        <TabItem Header="Core" > 
            <Grid Margin="5">
                <Grid.Height>
                    <MultiBinding Converter="{Converters1:AllTabContentEqualHeightConverter}">
                        <Binding Path="ActualHeight" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}"/>
                        <Binding Path="Items" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type TabControl}}"/>
                    </MultiBinding>
                </Grid.Height>

            ...

هل يمكن هذا؟

هل كانت مفيدة؟

المحلول 3

في الواقع، كان حل هذا الأمر أسهل على ما اعتقدت.منذ أن كان لدي قالب تحكم لـ TabControl على أية حال، قمت بتعيين ارتفاع ContentPresenter تقديم محتوى علامة التبويب المحددة.أفعل ذلك باستخدام محول يرتبط بعناصر ملف TabControl, ، يقيسها إذا لزم الأمر (باستخدام Measure) والشيكات DesiredSize للحجم الذي أحتاجه.

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var items = value as ItemCollection;

        if (items == null)
            return null;

        double max = 0;
        foreach (TabItem item in items)
        {
            var content = item.Content as FrameworkElement;
            if (content == null) continue;

            if (!content.IsMeasureValid)
                content.Measure(new Size(int.MaxValue, int.MaxValue));

            var height = content.DesiredSize.Height;
            if (max < height)
                max = height;
        }

        return max;
    }

هذا يعمل بشكل جيد، مع بعض التحذيرات:

  • يجب أن يكون كل محتوى علامة تبويب FrameworkElement
  • لا يتغير حجم المحتويات بمجرد تحميلها (لأن المحول يتم استدعاؤه فقط عندما تتغير خاصية العناصر، أي مرة واحدة فقط).

نصائح أخرى

ونعم يمكن القيام به: إعادة استخدام الشبكة، rowdefinitions مقابل كل-tabitem

مثال:

    <TabControl Grid.IsSharedSizeScope="True">
        <TabItem Header="Tab 1">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition SharedSizeGroup="xxx"/>
                </Grid.RowDefinitions>
            </Grid>
        </TabItem>
        <TabItem Header="Tab 2">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition SharedSizeGroup="xxx"/>
                </Grid.RowDefinitions>
            </Grid>
        </TabItem>
   </TabControl>

المشكلة هي أن TabControl يقوم بتفريغ وإعادة تحميل محتواه أثناء تبديل علامات التبويب.ولذلك فهو يعرف فقط حجم المحتوى الموجود في علامة التبويب النشطة حاليًا.يجب أن تكون قادرًا على تغيير TabControl بحيث يكون كذلك أبداً يدمر أطفاله، وهم موجودون دائمًا (لكن ربما مخفيين).

هذا بلوق وظيفة بواسطة إريك بيرك يجب أن تبدأ.مما يمكنني قوله من خلال تصفح منشوره، ستحتاج إلى تغييره بحيث:

  • يتم تحميل جميع الأطفال عند TabControl محمل.
  • يتم إخفاء الأطفال بدلاً من الانهيار عندما يكونون غير نشطين

وانها على الارجح ليس بالطريقة المناسبة WPF، ولكن، إذا كان لديك بالفعل كل عناصر المحتوى، هل يمكن ربما حلقة من خلالهم على الحمل وتعيين ذروة TabControl برمجيا.

وهذا عمل بالنسبة لي بالتزامن مع نهج Grid.IsSharedSizeScope هو مبين أعلاه.

ملاحظة يستخدم هذا SetCurrentValue بدلا من مجرد إعداد الخاصية SelectedIndex - وبهذه الطريقة نحافظ على الارتباطات المحتملة الحالية:

private void TabControl_OnLoaded(object sender, RoutedEventArgs e)
{
    //NOTE: loop through tab items to force measurement and size the tab control to the largest tab
    TabControl tabControl = (TabControl)sender;

    // backup selection
    int indexItemLast = tabControl.SelectedIndex;

    int itemCount = tabControl.Items.Count;

    for (
        int indexItem = (itemCount - 1);
        indexItem >= 0;
        indexItem--)
    {
        tabControl.SetCurrentValue(Selector.SelectedIndexProperty, indexItem);
        tabControl.UpdateLayout();
    }

    // restore selection
    tabControl.SetCurrentValue(Selector.SelectedIndexProperty, indexItemLast);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top