Skip to content

Commit 341c36c

Browse files
committed
Fixing name scope issue that would cause ElementName bindings to fail when used inside of a TransitioningContentBase.
Fixes #950
1 parent 019c5d6 commit 341c36c

File tree

7 files changed

+91
-74
lines changed

7 files changed

+91
-74
lines changed

MainDemo.Wpf/TransitionsDemo/TransitionsDemoHome.xaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@
2626
<smtx:XamlDisplay Key="transitions" Grid.Row="1">
2727
<!-- the transitioner will manage your transitions. notice how SelectedIndex is set to zero: the first slide (instead of the default of -1) -->
2828
<materialDesign:Transitioner SelectedIndex="0" AutoApplyTransitionOrigins="True">
29+
<materialDesign:Transitioner.InputBindings>
30+
<KeyBinding Key="Left" Command="{x:Static materialDesign:Transitioner.MovePreviousCommand}" />
31+
<KeyBinding Key="Right" Command="{x:Static materialDesign:Transitioner.MoveNextCommand}" />
32+
</materialDesign:Transitioner.InputBindings>
2933

3034
<!-- you can use a slide for each page, let's add a touch of fade for our first page -->
3135
<materialDesign:TransitionerSlide OpeningEffect="{materialDesign:TransitionEffect FadeIn}">

MaterialDesignThemes.Wpf/Transitions/IZIndexController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ namespace MaterialDesignThemes.Wpf.Transitions
22
{
33
public interface IZIndexController
44
{
5-
void Stack(params TransitionerSlide[] highestToLowest);
5+
void Stack(params TransitionerSlide[] highestToLowest);
66
}
77
}

MaterialDesignThemes.Wpf/Transitions/TransitionEffectTypeConverter.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,20 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT
1414

1515
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
1616
{
17-
TransitionEffectBase transitionEffect = null;
17+
TransitionEffectBase transitionEffect;
1818

19-
var stringValue = value as string;
20-
if (stringValue != null)
19+
if (value is string stringValue &&
20+
Enum.TryParse(stringValue, out TransitionEffectKind effectKind))
2121
{
22-
TransitionEffectKind effectKind;
23-
if (Enum.TryParse(stringValue, out effectKind))
24-
transitionEffect = new TransitionEffect(effectKind);
22+
transitionEffect = new TransitionEffect(effectKind);
2523
}
2624
else
25+
{
2726
transitionEffect = value as TransitionEffectBase;
27+
}
2828

2929
if (transitionEffect == null)
30-
throw new XamlParseException($"Could not parse to type {typeof (TransitionEffectKind).FullName} or {typeof (TransitionEffectBase).FullName}.");
30+
throw new XamlParseException($"Could not parse to type {typeof(TransitionEffectKind).FullName} or {typeof(TransitionEffectBase).FullName}.");
3131

3232
return transitionEffect;
3333
}

MaterialDesignThemes.Wpf/Transitions/Transitioner.cs

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Linq;
43
using System.Windows;
54
using System.Windows.Controls;
@@ -21,12 +20,12 @@ static Transitioner()
2120
}
2221

2322
/// <summary>
24-
/// Causes the the next slide to be displayed (affectively increments <see cref="SelectedIndex"/>).
23+
/// Causes the the next slide to be displayed (affectively increments <see cref="Selector.SelectedIndex"/>).
2524
/// </summary>
2625
public static RoutedCommand MoveNextCommand = new RoutedCommand();
2726

2827
/// <summary>
29-
/// Causes the the previous slide to be displayed (affectively decrements <see cref="SelectedIndex"/>).
28+
/// Causes the the previous slide to be displayed (affectively decrements <see cref="Selector.SelectedIndex"/>).
3029
/// </summary>
3130
public static RoutedCommand MovePreviousCommand = new RoutedCommand();
3231

@@ -41,24 +40,24 @@ static Transitioner()
4140
public static RoutedCommand MoveLastCommand = new RoutedCommand();
4241

4342
public static readonly DependencyProperty AutoApplyTransitionOriginsProperty = DependencyProperty.Register(
44-
"AutoApplyTransitionOrigins", typeof (bool), typeof (Transitioner), new PropertyMetadata(default(bool)));
45-
43+
"AutoApplyTransitionOrigins", typeof(bool), typeof(Transitioner), new PropertyMetadata(default(bool)));
44+
4645
/// <summary>
4746
/// If enabled, transition origins will be applied to wipes, according to where a transition was triggered from. For example, the mouse point where a user clicks a button.
4847
/// </summary>
4948
public bool AutoApplyTransitionOrigins
5049
{
51-
get { return (bool) GetValue(AutoApplyTransitionOriginsProperty); }
52-
set { SetValue(AutoApplyTransitionOriginsProperty, value); }
50+
get => (bool)GetValue(AutoApplyTransitionOriginsProperty);
51+
set => SetValue(AutoApplyTransitionOriginsProperty, value);
5352
}
5453

5554
public static readonly DependencyProperty DefaultTransitionOriginProperty = DependencyProperty.Register(
5655
"DefaultTransitionOrigin", typeof(Point), typeof(Transitioner), new PropertyMetadata(new Point(0.5, 0.5)));
5756

5857
public Point DefaultTransitionOrigin
5958
{
60-
get { return (Point)GetValue(DefaultTransitionOriginProperty); }
61-
set { SetValue(DefaultTransitionOriginProperty, value); }
59+
get => (Point)GetValue(DefaultTransitionOriginProperty);
60+
set => SetValue(DefaultTransitionOriginProperty, value);
6261
}
6362

6463
public Transitioner()
@@ -78,11 +77,11 @@ public Transitioner()
7877
protected override bool IsItemItsOwnContainerOverride(object item)
7978
{
8079
return item is TransitionerSlide;
81-
}
80+
}
8281

8382
protected override DependencyObject GetContainerForItemOverride()
8483
{
85-
return new TransitionerSlide();
84+
return new TransitionerSlide();
8685
}
8786

8887
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
@@ -190,17 +189,17 @@ private void ActivateFrame(int selectedIndex, int unselectedIndex)
190189
slide.SetCurrentValue(TransitionerSlide.StateProperty, TransitionerSlideState.Previous);
191190
}
192191
else
193-
{
192+
{
194193
slide.SetCurrentValue(TransitionerSlide.StateProperty, TransitionerSlideState.None);
195194
}
196-
Panel.SetZIndex(slide, 0);
195+
Panel.SetZIndex(slide, 0);
197196
}
198197

199198
if (newSlide != null)
200199
{
201200
newSlide.Opacity = 1;
202201
}
203-
202+
204203
if (oldSlide != null && newSlide != null)
205204
{
206205
var wipe = selectedIndex > unselectedIndex ? oldSlide.ForwardWipe : oldSlide.BackwardWipe;
@@ -220,23 +219,23 @@ private void ActivateFrame(int selectedIndex, int unselectedIndex)
220219
DoStack(oldSlide ?? newSlide);
221220
if (oldSlide != null)
222221
{
223-
oldSlide.Opacity = 0;
222+
oldSlide.Opacity = 0;
224223
}
225-
}
224+
}
226225

227226
_nextTransitionOrigin = null;
228227
}
229228

230229
private Point GetTransitionOrigin(TransitionerSlide slide)
231230
{
232-
if(_nextTransitionOrigin != null)
231+
if (_nextTransitionOrigin != null)
233232
{
234233
return _nextTransitionOrigin.Value;
235234
}
236235

237-
if(slide.ReadLocalValue(TransitionerSlide.TransitionOriginProperty) != DependencyProperty.UnsetValue)
236+
if (slide.ReadLocalValue(TransitionerSlide.TransitionOriginProperty) != DependencyProperty.UnsetValue)
238237
{
239-
return slide.TransitionOrigin;
238+
return slide.TransitionOrigin;
240239
}
241240

242241
return DefaultTransitionOrigin;

MaterialDesignThemes.Wpf/Transitions/TransitionerSlide.cs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,59 +19,59 @@ static TransitionerSlide()
1919
}
2020

2121
public static readonly DependencyProperty TransitionOriginProperty = DependencyProperty.Register(
22-
"TransitionOrigin", typeof(Point), typeof(Transitioner), new PropertyMetadata(new Point(0.5,0.5)));
22+
"TransitionOrigin", typeof(Point), typeof(Transitioner), new PropertyMetadata(new Point(0.5, 0.5)));
2323

2424
public Point TransitionOrigin
2525
{
26-
get { return (Point)GetValue(TransitionOriginProperty); }
27-
set { SetValue(TransitionOriginProperty, value); }
26+
get => (Point)GetValue(TransitionOriginProperty);
27+
set => SetValue(TransitionOriginProperty, value);
2828
}
2929

3030
public static RoutedEvent InTransitionFinished =
31-
EventManager.RegisterRoutedEvent("InTransitionFinished", RoutingStrategy.Bubble, typeof (RoutedEventHandler),
32-
typeof (TransitionerSlide));
31+
EventManager.RegisterRoutedEvent("InTransitionFinished", RoutingStrategy.Bubble, typeof(RoutedEventHandler),
32+
typeof(TransitionerSlide));
3333

3434
protected void OnInTransitionFinished(RoutedEventArgs e)
3535
{
3636
RaiseEvent(e);
3737
}
3838

39-
public static readonly DependencyProperty StateProperty = DependencyProperty.Register("State", typeof (TransitionerSlideState), typeof (TransitionerSlide), new PropertyMetadata(default(TransitionerSlideState), new PropertyChangedCallback(StatePropertyChangedCallback)));
39+
public static readonly DependencyProperty StateProperty = DependencyProperty.Register("State", typeof(TransitionerSlideState), typeof(TransitionerSlide), new PropertyMetadata(default(TransitionerSlideState), new PropertyChangedCallback(StatePropertyChangedCallback)));
4040

4141
private static void StatePropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
4242
{
43-
((TransitionerSlide) d).AnimateToState();
43+
((TransitionerSlide)d).AnimateToState();
4444
}
4545

4646
public TransitionerSlideState State
4747
{
48-
get { return (TransitionerSlideState) GetValue(StateProperty); }
49-
set { SetValue(StateProperty, value); }
48+
get => (TransitionerSlideState)GetValue(StateProperty);
49+
set => SetValue(StateProperty, value);
5050
}
5151

5252
public static readonly DependencyProperty ForwardWipeProperty = DependencyProperty.Register(
53-
"ForwardWipe", typeof (ITransitionWipe), typeof (TransitionerSlide), new PropertyMetadata(new CircleWipe()));
53+
"ForwardWipe", typeof(ITransitionWipe), typeof(TransitionerSlide), new PropertyMetadata(new CircleWipe()));
5454

5555
public ITransitionWipe ForwardWipe
5656
{
57-
get { return (ITransitionWipe) GetValue(ForwardWipeProperty); }
58-
set { SetValue(ForwardWipeProperty, value); }
57+
get => (ITransitionWipe)GetValue(ForwardWipeProperty);
58+
set => SetValue(ForwardWipeProperty, value);
5959
}
6060

6161
public static readonly DependencyProperty BackwardWipeProperty = DependencyProperty.Register(
62-
"BackwardWipe", typeof (ITransitionWipe), typeof (TransitionerSlide), new PropertyMetadata(new SlideOutWipe()));
62+
"BackwardWipe", typeof(ITransitionWipe), typeof(TransitionerSlide), new PropertyMetadata(new SlideOutWipe()));
6363

6464
public ITransitionWipe BackwardWipe
6565
{
66-
get { return (ITransitionWipe) GetValue(BackwardWipeProperty); }
67-
set { SetValue(BackwardWipeProperty, value); }
66+
get => (ITransitionWipe)GetValue(BackwardWipeProperty);
67+
set => SetValue(BackwardWipeProperty, value);
6868
}
6969

7070
private void AnimateToState()
7171
{
72-
if (State != TransitionerSlideState.Current) return;
72+
if (State != TransitionerSlideState.Current) return;
7373

7474
RunOpeningEffects();
75-
}
75+
}
7676
}
7777
}

MaterialDesignThemes.Wpf/Transitions/TransitioningContent.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ public TransitioningContent()
3030
}
3131

3232
public static readonly DependencyProperty RunHintProperty = DependencyProperty.Register(
33-
"RunHint", typeof(TransitioningContentRunHint), typeof(TransitioningContent), new PropertyMetadata(TransitioningContentRunHint.All));
33+
nameof(RunHint), typeof(TransitioningContentRunHint), typeof(TransitioningContent), new PropertyMetadata(TransitioningContentRunHint.All));
3434

3535
public TransitioningContentRunHint RunHint
3636
{
37-
get { return (TransitioningContentRunHint)GetValue(RunHintProperty); }
38-
set { SetValue(RunHintProperty, value); }
37+
get => (TransitioningContentRunHint)GetValue(RunHintProperty);
38+
set => SetValue(RunHintProperty, value);
3939
}
4040

4141
private void Run(TransitioningContentRunHint requiredHint)

MaterialDesignThemes.Wpf/Transitions/TransitioningContentBase.cs

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,73 +23,70 @@ public class TransitioningContentBase : ContentControl, ITransitionEffectSubject
2323
private SkewTransform _skewTransform;
2424
private TranslateTransform _translateTransform;
2525

26-
private bool _isOpeningEffectPending = false;
26+
private bool _isOpeningEffectPending;
2727

2828
static TransitioningContentBase()
2929
{
30-
DefaultStyleKeyProperty.OverrideMetadata(typeof (TransitioningContentBase), new FrameworkPropertyMetadata(typeof (TransitioningContentBase)));
31-
}
32-
33-
public TransitioningContentBase()
34-
{
35-
NameScope.SetNameScope(this, new NameScope());
30+
DefaultStyleKeyProperty.OverrideMetadata(typeof(TransitioningContentBase), new FrameworkPropertyMetadata(typeof(TransitioningContentBase)));
3631
}
3732

3833
public override void OnApplyTemplate()
3934
{
35+
FrameworkElement nameScopeRoot = GetNameScopeRoot();
36+
4037
_matrixTransform = GetTemplateChild(MatrixTransformPartName) as MatrixTransform;
4138
_rotateTransform = GetTemplateChild(RotateTransformPartName) as RotateTransform;
4239
_scaleTransform = GetTemplateChild(ScaleTransformPartName) as ScaleTransform;
4340
_skewTransform = GetTemplateChild(SkewTransformPartName) as SkewTransform;
4441
_translateTransform = GetTemplateChild(TranslateTransformPartName) as TranslateTransform;
45-
42+
4643
UnregisterNames(MatrixTransformPartName, RotateTransformPartName, ScaleTransformPartName, SkewTransformPartName, TranslateTransformPartName);
4744
if (_matrixTransform != null)
48-
RegisterName(MatrixTransformPartName, _matrixTransform);
45+
nameScopeRoot.RegisterName(MatrixTransformPartName, _matrixTransform);
4946
if (_rotateTransform != null)
50-
RegisterName(RotateTransformPartName, _rotateTransform);
47+
nameScopeRoot.RegisterName(RotateTransformPartName, _rotateTransform);
5148
if (_scaleTransform != null)
52-
RegisterName(ScaleTransformPartName, _scaleTransform);
49+
nameScopeRoot.RegisterName(ScaleTransformPartName, _scaleTransform);
5350
if (_skewTransform != null)
54-
RegisterName(SkewTransformPartName, _skewTransform);
51+
nameScopeRoot.RegisterName(SkewTransformPartName, _skewTransform);
5552
if (_translateTransform != null)
56-
RegisterName(TranslateTransformPartName, _translateTransform);
53+
nameScopeRoot.RegisterName(TranslateTransformPartName, _translateTransform);
5754

5855
base.OnApplyTemplate();
5956

6057
RunOpeningEffects();
61-
}
6258

63-
private void UnregisterNames(params string[] names)
64-
{
65-
foreach (var name in names.Where(n => FindName(n) != null))
59+
void UnregisterNames(params string[] names)
6660
{
67-
UnregisterName(name);
68-
}
61+
foreach (var name in names.Where(n => FindName(n) != null))
62+
{
63+
UnregisterName(name);
64+
}
65+
}
6966
}
7067

71-
public static readonly DependencyProperty OpeningEffectProperty = DependencyProperty.Register("OpeningEffect", typeof (TransitionEffectBase), typeof (TransitioningContentBase), new PropertyMetadata(default(TransitionEffectBase)));
68+
public static readonly DependencyProperty OpeningEffectProperty = DependencyProperty.Register("OpeningEffect", typeof(TransitionEffectBase), typeof(TransitioningContentBase), new PropertyMetadata(default(TransitionEffectBase)));
7269

7370
/// <summary>
7471
/// Gets or sets the transition to run when the content is loaded and made visible.
7572
/// </summary>
7673
[TypeConverter(typeof(TransitionEffectTypeConverter))]
7774
public TransitionEffectBase OpeningEffect
7875
{
79-
get { return (TransitionEffectBase) GetValue(OpeningEffectProperty); }
80-
set { SetValue(OpeningEffectProperty, value); }
76+
get => (TransitionEffectBase)GetValue(OpeningEffectProperty);
77+
set => SetValue(OpeningEffectProperty, value);
8178
}
8279

8380
public static readonly DependencyProperty OpeningEffectsOffsetProperty = DependencyProperty.Register(
84-
"OpeningEffectsOffset", typeof (TimeSpan), typeof (TransitioningContentBase), new PropertyMetadata(default(TimeSpan)));
81+
"OpeningEffectsOffset", typeof(TimeSpan), typeof(TransitioningContentBase), new PropertyMetadata(default(TimeSpan)));
8582

8683
/// <summary>
8784
/// Delay offset to be applied to all opening effect transitions.
8885
/// </summary>
8986
public TimeSpan OpeningEffectsOffset
9087
{
91-
get { return (TimeSpan) GetValue(OpeningEffectsOffsetProperty); }
92-
set { SetValue(OpeningEffectsOffsetProperty, value); }
88+
get => (TimeSpan)GetValue(OpeningEffectsOffsetProperty);
89+
set => SetValue(OpeningEffectsOffsetProperty, value);
9390
}
9491

9592
/// <summary>
@@ -99,7 +96,7 @@ public TimeSpan OpeningEffectsOffset
9996

10097
string ITransitionEffectSubject.MatrixTransformName => MatrixTransformPartName;
10198

102-
string ITransitionEffectSubject.RotateTransformName => RotateTransformPartName;
99+
string ITransitionEffectSubject.RotateTransformName => RotateTransformPartName;
103100

104101
string ITransitionEffectSubject.ScaleTransformName => ScaleTransformPartName;
105102

@@ -127,7 +124,24 @@ protected virtual void RunOpeningEffects()
127124
storyboard.Children.Add(effect);
128125
}
129126

130-
storyboard.Begin(this);
127+
storyboard.Begin(GetNameScopeRoot());
128+
}
129+
130+
private FrameworkElement GetNameScopeRoot()
131+
{
132+
//https://github.com/ButchersBoy/MaterialDesignInXamlToolkit/issues/950
133+
//Only set the NameScope if the child does not already have a TemplateNameScope set
134+
if (GetVisualChild(0) is FrameworkElement fe && NameScope.GetNameScope(fe) != null)
135+
{
136+
return fe;
137+
}
138+
139+
if (NameScope.GetNameScope(this) == null)
140+
{
141+
NameScope.SetNameScope(this, new NameScope());
142+
}
143+
144+
return this;
131145
}
132146
}
133147
}

0 commit comments

Comments
 (0)