Browse Source

Make TabControl/Deck work again.

pull/69/head
Steven Kirk 11 years ago
parent
commit
77e81c4360
  1. 36
      Perspex.Controls/Deck.cs
  2. 2
      Perspex.Controls/Generators/ItemContainerGenerator.cs
  3. 190
      Perspex.Controls/Presenters/DeckPresenter.cs
  4. 21
      Perspex.Controls/Primitives/SelectingItemsControl.cs
  5. 70
      Perspex.Controls/TabControl.cs
  6. 2
      Perspex.Themes.Default/DeckStyle.cs
  7. 3
      Tests/Perspex.Controls.UnitTests/DeckTests.cs
  8. 1
      Tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  9. 83
      Tests/Perspex.Controls.UnitTests/Presenters/DeckPresenterTests.cs
  10. 24
      Tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs
  11. 18
      Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs
  12. 28
      Tests/Perspex.Controls.UnitTests/TabControlTests.cs

36
Perspex.Controls/Deck.cs

@ -6,57 +6,59 @@
namespace Perspex.Controls
{
using System.Collections;
using Perspex.Animation;
using Perspex.Controls.Generators;
using Perspex.Controls.Primitives;
using Perspex.Controls.Utils;
using Perspex.Input;
/// <summary>
/// A selecting items control that displays a single item that fills the control.
/// An items control that displays its items as pages that fill the control.
/// </summary>
public class Deck : SelectingItemsControl
{
/// <summary>
/// Defines the <see cref="Transition"/> property.
/// </summary>
public static readonly PerspexProperty<IPageTransition> TransitionProperty =
PerspexProperty.Register<Deck, IPageTransition>("Transition");
private static readonly ItemsPanelTemplate PanelTemplate =
/// <summary>
/// The default value of <see cref="IItemsPanel"/> for <see cref="Deck"/>.
/// </summary>
private static readonly ItemsPanelTemplate PanelTemplate =
new ItemsPanelTemplate(() => new Panel());
/// <summary>
/// Initializes static members of the <see cref="Deck"/> class.
/// </summary>
static Deck()
{
ItemsPanelProperty.OverrideDefaultValue(typeof(Deck), PanelTemplate);
AutoSelectProperty.OverrideDefaultValue<Deck>(true);
ItemsPanelProperty.OverrideDefaultValue<Deck>(PanelTemplate);
}
/// <summary>
/// Gets or sets the transition to use when moving between pages.
/// </summary>
public IPageTransition Transition
{
get { return this.GetValue(TransitionProperty); }
set { this.SetValue(TransitionProperty, value); }
}
protected override void ItemsChanged(PerspexPropertyChangedEventArgs e)
{
base.ItemsChanged(e);
var items = this.Items;
if (items != null && items.Count() > 0)
{
this.SelectedIndex = 0;
}
}
/// <inheritdoc/>
protected override void OnKeyDown(KeyEventArgs e)
{
// Ignore key presses.
}
/// <inheritdoc/>
protected override void OnPointerPressed(PointerPressEventArgs e)
{
// Ignore pointer presses.
}
/// <inheritdoc/>
protected override void OnTemplateApplied()
{
base.OnTemplateApplied();

2
Perspex.Controls/Generators/ItemContainerGenerator.cs

@ -92,7 +92,7 @@ namespace Perspex.Controls.Generators
if (container != null)
{
result.Add(container);
this.containers[i] = null;
this.containers.Remove(i);
}
}

190
Perspex.Controls/Presenters/DeckPresenter.cs

@ -6,74 +6,132 @@
namespace Perspex.Controls.Presenters
{
using System;
using System.Collections;
using System.Linq;
using System.Reactive.Linq;
using System.Threading.Tasks;
using Perspex.Animation;
using Perspex.Controls.Generators;
using Perspex.Controls.Primitives;
using Perspex.Controls.Utils;
using Perspex.Input;
using Perspex.Styling;
using System;
using System.Collections;
using System.Linq;
using System.Reactive.Linq;
/// <summary>
/// Displays pages inside an <see cref="ItemsControl"/>.
/// </summary>
public class DeckPresenter : Control, IItemsPresenter, ITemplatedControl
{
/// <summary>
/// Defines the <see cref="Items"/> property.
/// </summary>
public static readonly PerspexProperty<IEnumerable> ItemsProperty =
ItemsControl.ItemsProperty.AddOwner<DeckPresenter>();
/// <summary>
/// Defines the <see cref="ItemsPanel"/> property.
/// </summary>
public static readonly PerspexProperty<ItemsPanelTemplate> ItemsPanelProperty =
ItemsControl.ItemsPanelProperty.AddOwner<DeckPresenter>();
public static readonly PerspexProperty<object> SelectedItemProperty =
SelectingItemsControl.SelectedItemProperty.AddOwner<DeckPresenter>();
/// <summary>
/// Defines the <see cref="SelectedIndex"/> property.
/// </summary>
public static readonly PerspexProperty<int> SelectedIndexProperty =
SelectingItemsControl.SelectedIndexProperty.AddOwner<DeckPresenter>();
/// <summary>
/// Defines the <see cref="Transition"/> property.
/// </summary>
public static readonly PerspexProperty<IPageTransition> TransitionProperty =
Deck.TransitionProperty.AddOwner<DeckPresenter>();
private bool createdPanel;
public DeckPresenter()
private IItemContainerGenerator generator;
/// <summary>
/// Initializes static members of the <see cref="DeckPresenter"/> class.
/// </summary>
static DeckPresenter()
{
this.GetObservableWithHistory(SelectedItemProperty).Subscribe(this.SelectedItemChanged);
SelectedIndexProperty.Changed.AddClassHandler<DeckPresenter>(x => x.SelectedIndexChanged);
}
/// <summary>
/// Gets the <see cref="IItemContainerGenerator"/> used to generate item container
/// controls.
/// </summary>
public IItemContainerGenerator ItemContainerGenerator
{
get;
private set;
get
{
if (this.generator == null)
{
var i = this.TemplatedParent as ItemsControl;
this.generator = i?.ItemContainerGenerator ?? new ItemContainerGenerator(this);
}
return this.generator;
}
set
{
if (this.generator != null)
{
throw new InvalidOperationException("ItemContainerGenerator is already set.");
}
this.generator = value;
}
}
/// <summary>
/// Gets or sets the items to display.
/// </summary>
public IEnumerable Items
{
get { return this.GetValue(ItemsProperty); }
set { this.SetValue(ItemsProperty, value); }
}
/// <summary>
/// Gets or sets the panel used to display the pages.
/// </summary>
public ItemsPanelTemplate ItemsPanel
{
get { return this.GetValue(ItemsPanelProperty); }
set { this.SetValue(ItemsPanelProperty, value); }
}
public object SelectedItem
/// <summary>
/// Gets or sets the index of the selected page.
/// </summary>
public int SelectedIndex
{
get { return this.GetValue(SelectedItemProperty); }
set { this.SetValue(SelectedItemProperty, value); }
get { return this.GetValue(SelectedIndexProperty); }
set { this.SetValue(SelectedIndexProperty, value); }
}
/// <summary>
/// Gets the panel used to display the pages.
/// </summary>
public Panel Panel
{
get;
private set;
}
/// <summary>
/// Gets or sets a transition to use when switching pages.
/// </summary>
public IPageTransition Transition
{
get { return this.GetValue(TransitionProperty); }
set { this.SetValue(TransitionProperty, value); }
}
/// <inheritdoc/>
public override sealed void ApplyTemplate()
{
if (!this.createdPanel)
@ -82,81 +140,73 @@ namespace Perspex.Controls.Presenters
}
}
protected override Size MeasureOverride(Size availableSize)
{
this.Panel.Measure(availableSize);
return this.Panel.DesiredSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
this.Panel.Arrange(new Rect(finalSize));
return finalSize;
}
/// <summary>
/// Creates the <see cref="Panel"/>.
/// </summary>
private void CreatePanel()
{
this.ClearVisualChildren();
this.Panel = this.ItemsPanel.Build();
this.Panel.TemplatedParent = this;
((IItemsPanel)this.Panel).ChildLogicalParent = this.TemplatedParent as ILogical;
this.AddVisualChild(this.Panel);
this.createdPanel = true;
if (this.SelectedItem != null)
if (this.ItemsPanel != null)
{
this.SelectedItemChanged(Tuple.Create<object, object>(null, this.SelectedItem));
this.Panel = this.ItemsPanel.Build();
this.Panel.TemplatedParent = this;
((IItemsPanel)this.Panel).ChildLogicalParent = this.TemplatedParent as ILogical;
this.AddVisualChild(this.Panel);
this.createdPanel = true;
var task = this.MoveToPage(-1, this.SelectedIndex);
}
}
private IItemContainerGenerator GetGenerator()
/// <summary>
/// Moves to the selected page, animating if a <see cref="Transition"/> is set.
/// </summary>
/// <param name="fromIndex">The index of the old page.</param>
/// <param name="toIndex">The index of the new page.</param>
/// <returns>A task tracking the animation.</returns>
private async Task MoveToPage(int fromIndex, int toIndex)
{
if (this.ItemContainerGenerator == null)
var generator = this.ItemContainerGenerator;
IControl from = null;
IControl to = null;
if (fromIndex != -1)
{
ItemsControl i = this.TemplatedParent as ItemsControl;
this.ItemContainerGenerator = i?.ItemContainerGenerator ?? new ItemContainerGenerator(this);
from = generator.ContainerFromIndex(fromIndex);
}
return this.ItemContainerGenerator;
}
private async void SelectedItemChanged(Tuple<object, object> value)
{
if (this.createdPanel)
if (toIndex != -1)
{
var generator = this.GetGenerator();
IControl from = null;
IControl to = null;
int fromIndex = -1;
int toIndex = -1;
var item = this.Items.Cast<object>().ElementAt(toIndex);
to = generator.CreateContainers(toIndex, new[] { item }, null).FirstOrDefault();
if (value.Item1 != null)
if (to != null)
{
fromIndex = this.Items.IndexOf(value.Item1);
from = generator.ContainerFromIndex(fromIndex);
this.Panel.Children.Add(to);
}
}
if (value.Item2 != null)
{
toIndex = this.Items.IndexOf(value.Item2);
to = generator.CreateContainers(toIndex, new[] { value.Item2 }, null).FirstOrDefault();
if (to != null)
{
this.Panel.Children.Add(to);
}
}
if (this.Transition != null)
{
await this.Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex);
}
if (this.Transition != null)
{
await this.Transition.Start((Visual)from, (Visual)to, fromIndex < toIndex);
}
if (from != null)
{
this.Panel.Children.Remove(from);
generator.RemoveContainers(fromIndex, 1);
}
}
if (from != null)
{
this.Panel.Children.Remove(from);
generator.RemoveContainers(fromIndex, 1);
}
/// <summary>
/// Called when the <see cref="SelectedIndex"/> property changes.
/// </summary>
/// <param name="e">The event args.</param>
private void SelectedIndexChanged(PerspexPropertyChangedEventArgs e)
{
if (this.Panel != null)
{
var task = this.MoveToPage((int)e.OldValue, (int)e.NewValue);
}
}
}

21
Perspex.Controls/Primitives/SelectingItemsControl.cs

@ -105,7 +105,15 @@ namespace Perspex.Controls.Primitives
protected override void ItemsChanged(PerspexPropertyChangedEventArgs e)
{
base.ItemsChanged(e);
this.SelectedIndex = IndexOf((IEnumerable)e.NewValue, this.SelectedItem);
if (this.SelectedIndex != -1)
{
this.SelectedIndex = IndexOf((IEnumerable)e.NewValue, this.SelectedItem);
}
else if (this.AutoSelect && this.Items != null & this.Items.Cast<object>().Any())
{
this.SelectedIndex = 0;
}
}
/// <inheritdoc/>
@ -115,6 +123,13 @@ namespace Perspex.Controls.Primitives
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
if (this.AutoSelect && this.SelectedIndex == -1)
{
this.SelectedIndex = 0;
}
break;
case NotifyCollectionChangedAction.Remove:
case NotifyCollectionChangedAction.Replace:
var selectedIndex = this.SelectedIndex;
@ -252,10 +267,6 @@ namespace Perspex.Controls.Primitives
var container = containers.Items[selectedIndex - containers.StartingIndex];
MarkContainerSelected(container, true);
}
else if (selectedIndex == -1 && this.AutoSelect)
{
this.SelectedIndex = 0;
}
}
/// <summary>

70
Perspex.Controls/TabControl.cs

@ -6,82 +6,118 @@
namespace Perspex.Controls
{
using System;
using System.Reactive.Linq;
using Perspex.Animation;
using Perspex.Collections;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.Input;
/// <summary>
/// A tab control that displays a tab strip along with the content of the selected tab.
/// </summary>
public class TabControl : SelectingItemsControl, ILogical
{
/// <summary>
/// Defines the <see cref="SelectedContent"/> property.
/// </summary>
public static readonly PerspexProperty<object> SelectedContentProperty =
PerspexProperty.Register<TabControl, object>("SelectedContent");
/// <summary>
/// Defines the <see cref="SelectedTab"/> property.
/// </summary>
public static readonly PerspexProperty<TabItem> SelectedTabProperty =
PerspexProperty.Register<TabControl, TabItem>("SelectedTab");
/// <summary>
/// Defines the <see cref="Transition"/> property.
/// </summary>
public static readonly PerspexProperty<IPageTransition> TransitionProperty =
Deck.TransitionProperty.AddOwner<TabControl>();
private PerspexReadOnlyListView<ILogical> logicalChildren =
private PerspexReadOnlyListView<ILogical> logicalChildren =
new PerspexReadOnlyListView<ILogical>();
/// <summary>
/// Initializes static members of the <see cref="TabControl"/> class.
/// </summary>
static TabControl()
{
AutoSelectProperty.OverrideDefaultValue<TabControl>(true);
FocusableProperty.OverrideDefaultValue<TabControl>(false);
SelectedIndexProperty.Changed.AddClassHandler<TabControl>(x => x.SelectedIndexChanged);
}
/// <summary>
/// Initializes a new instance of the <see cref="TabControl"/> class.
/// </summary>
public TabControl()
{
this.BindTwoWay(SelectedTabProperty, this, SelectingItemsControl.SelectedItemProperty);
this.GetObservable(SelectedItemProperty).Subscribe(x =>
{
ContentControl c = x as ContentControl;
object content = (c != null) ? c.Content : c;
this.SetValue(SelectedTabProperty, x);
this.SetValue(SelectedContentProperty, content);
});
}
/// <summary>
/// Gets the content of the selected tab.
/// </summary>
public object SelectedContent
{
get { return this.GetValue(SelectedContentProperty); }
set { this.SetValue(SelectedContentProperty, value); }
private set { this.SetValue(SelectedContentProperty, value); }
}
/// <summary>
/// Gets the <see cref="SelectedItem"/> as a <see cref="TabItem"/>.
/// </summary>
public TabItem SelectedTab
{
get { return this.GetValue(SelectedTabProperty); }
set { this.SetValue(SelectedTabProperty, value); }
private set { this.SetValue(SelectedTabProperty, value); }
}
/// <summary>
/// Gets or sets the transition to use when switching tabs.
/// </summary>
public IPageTransition Transition
{
get { return this.GetValue(TransitionProperty); }
set { this.SetValue(TransitionProperty, value); }
}
/// <summary>
/// Gets the logical children of the control.
/// </summary>
IPerspexReadOnlyList<ILogical> ILogical.LogicalChildren
{
get { return this.logicalChildren; }
}
/// <inheritdoc/>
protected override void OnKeyDown(KeyEventArgs e)
{
// Don't handle keypresses.
}
Deck deck;
/// <inheritdoc/>
protected override void OnTemplateApplied()
{
base.OnTemplateApplied();
this.deck = this.GetTemplateChild<Deck>("deck");
var deck = this.GetTemplateChild<Deck>("deck");
this.logicalChildren.Source = ((ILogical)deck).LogicalChildren;
}
/// <summary>
/// Called when the <see cref="SelectedIndex"/> property changes.
/// </summary>
/// <param name="e">The event args.</param>
private void SelectedIndexChanged(PerspexPropertyChangedEventArgs e)
{
if ((int)e.NewValue != -1)
{
var item = this.SelectedItem as IContentControl;
var content = item?.Content ?? item;
this.SelectedTab = item as TabItem;
this.SelectedContent = content;
}
}
}
}

2
Perspex.Themes.Default/DeckStyle.cs

@ -35,7 +35,7 @@ namespace Perspex.Themes.Default
Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~Deck.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~Deck.ItemsPanelProperty],
[~DeckPresenter.SelectedItemProperty] = control[~Deck.SelectedItemProperty],
[~DeckPresenter.SelectedIndexProperty] = control[~Deck.SelectedIndexProperty],
[~DeckPresenter.TransitionProperty] = control[~Deck.TransitionProperty],
};
}

3
Tests/Perspex.Controls.UnitTests/DeckTests.cs

@ -29,6 +29,7 @@ namespace Perspex.Controls.UnitTests
target.ApplyTemplate();
Assert.Equal(0, target.SelectedIndex);
Assert.Equal("Foo", target.SelectedItem);
}
@ -61,7 +62,7 @@ namespace Perspex.Controls.UnitTests
Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~Deck.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~Deck.ItemsPanelProperty],
[~DeckPresenter.SelectedItemProperty] = control[~Deck.SelectedItemProperty],
[~DeckPresenter.SelectedIndexProperty] = control[~Deck.SelectedIndexProperty],
[~DeckPresenter.TransitionProperty] = control[~Deck.TransitionProperty],
};
}

1
Tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj

@ -95,6 +95,7 @@
<Compile Include="Parsers\GridLengthsParserTests.cs" />
<Compile Include="PopupTests.cs" />
<Compile Include="DropDownTests.cs" />
<Compile Include="Presenters\DeckPresenterTests.cs" />
<Compile Include="Presenters\ItemsPresenterTests.cs" />
<Compile Include="Presenters\ScrollContentPresenterTests.cs" />
<Compile Include="Primitives\ScrollBarTests.cs" />

83
Tests/Perspex.Controls.UnitTests/Presenters/DeckPresenterTests.cs

@ -0,0 +1,83 @@
// -----------------------------------------------------------------------
// <copyright file="DeckPresenterTests.cs" company="Steven Kirk">
// Copyright 2015 MIT Licence. See licence.md for more information.
// </copyright>
// -----------------------------------------------------------------------
namespace Perspex.Controls.UnitTests.Presenters
{
using Perspex.Controls.Generators;
using Perspex.Controls.Presenters;
using Xunit;
public class DeckPresenterTests
{
[Fact]
public void ApplyTemplate_Should_Create_Panel()
{
var target = new DeckPresenter
{
ItemsPanel = new ItemsPanelTemplate(() => new Panel()),
};
target.ApplyTemplate();
Assert.IsType<Panel>(target.Panel);
}
[Fact]
public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl()
{
var parent = new TestItemsControl();
var target = new DeckPresenter
{
TemplatedParent = parent,
};
Assert.IsType<TypedItemContainerGenerator<TestItem>>(target.ItemContainerGenerator);
}
[Fact]
public void Setting_SelectedIndex_Should_Show_Page()
{
var target = new DeckPresenter
{
Items = new[] { "foo", "bar" },
SelectedIndex = 0,
};
target.ApplyTemplate();
Assert.IsType<TextBlock>(target.Panel.Children[0]);
Assert.Equal("foo", ((TextBlock)target.Panel.Children[0]).Text);
}
[Fact]
public void Changing_SelectedIndex_Should_Show_Page()
{
var target = new DeckPresenter
{
Items = new[] { "foo", "bar" },
SelectedIndex = 0,
};
target.ApplyTemplate();
target.SelectedIndex = 1;
Assert.IsType<TextBlock>(target.Panel.Children[0]);
Assert.Equal("bar", ((TextBlock)target.Panel.Children[0]).Text);
}
private class TestItem : ContentControl
{
}
private class TestItemsControl : ItemsControl
{
protected override IItemContainerGenerator CreateItemContainerGenerator()
{
return new TypedItemContainerGenerator<TestItem>(this);
}
}
}
}

24
Tests/Perspex.Controls.UnitTests/Presenters/ItemsPresenterTests.cs

@ -50,6 +50,18 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.IsType<ListBoxItem>(target.Panel.Children[1]);
}
[Fact]
public void ItemContainerGenerator_Should_Be_Picked_Up_From_TemplatedControl()
{
var parent = new TestItemsControl();
var target = new ItemsPresenter
{
TemplatedParent = parent,
};
Assert.IsType<TypedItemContainerGenerator<TestItem>>(target.ItemContainerGenerator);
}
[Fact]
public void Should_Remove_Containers()
{
@ -174,5 +186,17 @@ namespace Perspex.Controls.UnitTests.Presenters
Assert.Equal(target.Panel, child);
}
private class TestItem : ContentControl
{
}
private class TestItemsControl : ItemsControl
{
protected override IItemContainerGenerator CreateItemContainerGenerator()
{
return new TypedItemContainerGenerator<TestItem>(this);
}
}
}
}

18
Tests/Perspex.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs

@ -31,6 +31,24 @@ namespace Perspex.Controls.UnitTests.Primitives
Assert.Equal("foo", target.SelectedItem);
}
[Fact]
public void First_Item_Should_Be_Selected_When_Added()
{
var items = new PerspexList<string>();
var target = new SelectingItemsControl
{
AutoSelect = true,
Items = items,
Template = this.Template(),
};
target.ApplyTemplate();
items.Add("foo");
Assert.Equal(0, target.SelectedIndex);
Assert.Equal("foo", target.SelectedItem);
}
[Fact]
public void Item_Should_Be_Selected_When_Selection_Removed()
{

28
Tests/Perspex.Controls.UnitTests/TabControlTests.cs

@ -45,7 +45,7 @@ namespace Perspex.Controls.UnitTests
}
[Fact]
public void Setting_SelectedItem_Should_Set_SelectedTab()
public void SelectedContent_Should_Initially_Be_First_Tab_Content()
{
var target = new TabControl
{
@ -54,23 +54,24 @@ namespace Perspex.Controls.UnitTests
{
new TabItem
{
Name = "first"
Name = "first",
Content = "foo",
},
new TabItem
{
Name = "second"
Name = "second",
Content = "bar",
},
}
};
target.ApplyTemplate();
target.SelectedItem = target.Items.Cast<TabItem>().ElementAt(1);
Assert.Same(target.SelectedTab, target.SelectedItem);
Assert.Equal("foo", target.SelectedContent);
}
[Fact]
public void Setting_SelectedTab_Should_Set_SelectedItem()
public void Setting_SelectedItem_Should_Set_SelectedTab()
{
var target = new TabControl
{
@ -79,19 +80,22 @@ namespace Perspex.Controls.UnitTests
{
new TabItem
{
Name = "first"
Name = "first",
Content = "foo",
},
new TabItem
{
Name = "second"
Name = "second",
Content = "bar",
},
}
};
target.ApplyTemplate();
target.SelectedTab = target.Items.Cast<TabItem>().ElementAt(1);
target.SelectedItem = target.Items.Cast<TabItem>().ElementAt(1);
Assert.Same(target.SelectedItem, target.SelectedTab);
Assert.Same(target.SelectedTab, target.SelectedItem);
Assert.Equal("bar", target.SelectedContent);
}
[Fact]
@ -145,7 +149,7 @@ namespace Perspex.Controls.UnitTests
}
}
};
}
}
private Control CreateTabStripTemplate(TabStrip parent)
{
@ -163,7 +167,7 @@ namespace Perspex.Controls.UnitTests
Name = "itemsPresenter",
[~ItemsPresenter.ItemsProperty] = control[~Deck.ItemsProperty],
[~ItemsPresenter.ItemsPanelProperty] = control[~Deck.ItemsPanelProperty],
[~DeckPresenter.SelectedItemProperty] = control[~Deck.SelectedItemProperty],
[~DeckPresenter.SelectedIndexProperty] = control[~Deck.SelectedIndexProperty],
[~DeckPresenter.TransitionProperty] = control[~Deck.TransitionProperty],
};
}

Loading…
Cancel
Save