mirror of https://github.com/AMT-Cheif/Stylet.git
Add more unit tests
This commit is contained in:
parent
d648b264d1
commit
43fe090fa9
2
Rakefile
2
Rakefile
|
@ -46,7 +46,7 @@ end
|
|||
desc "Generate code coverage reports for CONFIG (or Debug)"
|
||||
task :cover => [:build, COVERAGE_DIR] do |t|
|
||||
sh OPENCOVER_CONSOLE, %Q{-register:user -target:"#{NUNIT_CONSOLE}" -filter:+[Stylet]* -targetargs:"#{UNIT_TESTS_DLL} /noshadow" -output:"#{COVERAGE_FILE}"}
|
||||
sh REPORT_GENERATOR, %Q{"-reports:#{COVERAGE_FILE}" "-targetdir:#{COVERAGE_DIR}"}
|
||||
sh REPORT_GENERATOR, %Q{-reports:"#{COVERAGE_FILE}" "-targetdir:#{COVERAGE_DIR}"}
|
||||
rm 'TestResult.xml'
|
||||
end
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace Stylet
|
|||
this.ConfigureResources();
|
||||
this.Configure();
|
||||
|
||||
View.ViewManager = IoC.Get<IViewManager>();
|
||||
IoC.Get<IWindowManager>().ShowWindow(IoC.Get<TRootViewModel>());
|
||||
}
|
||||
|
||||
|
|
|
@ -12,14 +12,7 @@ namespace Stylet
|
|||
public class View : DependencyObject
|
||||
{
|
||||
private static readonly ContentPropertyAttribute defaultContentProperty = new ContentPropertyAttribute("Content");
|
||||
private static IViewManager viewManager;
|
||||
|
||||
static View()
|
||||
{
|
||||
// Don't complain that IoC is not initialized if we're in design mode
|
||||
if (!Execute.InDesignMode)
|
||||
viewManager = IoC.Get<IViewManager>();
|
||||
}
|
||||
public static IViewManager ViewManager;
|
||||
|
||||
public static object GetActionTarget(DependencyObject obj)
|
||||
{
|
||||
|
@ -45,7 +38,7 @@ namespace Stylet
|
|||
}
|
||||
|
||||
public static readonly DependencyProperty ModelProperty =
|
||||
DependencyProperty.RegisterAttached("Model", typeof(object), typeof(View), new PropertyMetadata(null, (d, e) => viewManager.OnModelChanged(d, e) ));
|
||||
DependencyProperty.RegisterAttached("Model", typeof(object), typeof(View), new PropertyMetadata(null, (d, e) => ViewManager.OnModelChanged(d, e) ));
|
||||
|
||||
|
||||
public static void SetContentProperty(DependencyObject targetLocation, UIElement view)
|
||||
|
|
|
@ -63,7 +63,7 @@ namespace Stylet
|
|||
}
|
||||
}
|
||||
|
||||
public virtual Type LocalViewForModel(Type modelType)
|
||||
public virtual Type LocateViewForModel(Type modelType)
|
||||
{
|
||||
var viewName = Regex.Replace(modelType.FullName, @"ViewModel", "View");
|
||||
// TODO: This might need some more thinking
|
||||
|
@ -77,7 +77,7 @@ namespace Stylet
|
|||
|
||||
public virtual UIElement CreateViewForModel(object model)
|
||||
{
|
||||
var viewType = this.LocalViewForModel(model.GetType());
|
||||
var viewType = this.LocateViewForModel(model.GetType());
|
||||
|
||||
if (viewType.IsInterface || viewType.IsAbstract || !typeof(UIElement).IsAssignableFrom(viewType))
|
||||
throw new Exception(String.Format("Found type for view: {0}, but it wasn't a class derived from UIElement", viewType.Name));
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
|
@ -37,10 +38,11 @@ namespace Stylet
|
|||
internal void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
TSource source;
|
||||
if (this.source.TryGetTarget(out source))
|
||||
var got = this.source.TryGetTarget(out source);
|
||||
// We should never hit this case. The PropertyChangedeventManager shouldn't call us if the source became null
|
||||
Debug.Assert(got);
|
||||
if (got)
|
||||
this.handler(this.valueSelector(source));
|
||||
else
|
||||
this.remover(this);
|
||||
}
|
||||
|
||||
public void Unbind()
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet.Xaml;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BoolToVisibilityConverterTests
|
||||
{
|
||||
private BoolToVisibilityConverter converter;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.converter = new BoolToVisibilityConverter();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void InstanceReturnsSingleton()
|
||||
{
|
||||
Assert.IsNotNull(BoolToVisibilityConverter.Instance);
|
||||
Assert.AreEqual(BoolToVisibilityConverter.Instance, BoolToVisibilityConverter.Instance);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertReturnsNullIfValueNotBool()
|
||||
{
|
||||
var result = this.converter.Convert(new object(), null, null, null);
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertReturnsVisibleForTrueByDefault()
|
||||
{
|
||||
var result = this.converter.Convert(true, null, null, null);
|
||||
Assert.AreEqual(Visibility.Visible, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertReturnsSetTrueVisibility()
|
||||
{
|
||||
this.converter.TrueVisibility = Visibility.Hidden;
|
||||
var result = this.converter.Convert(true, null, null, null);
|
||||
Assert.AreEqual(Visibility.Hidden, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertReturnsCollapsedForFalseByDefault()
|
||||
{
|
||||
var result = this.converter.Convert(false, null, null, null);
|
||||
Assert.AreEqual(Visibility.Collapsed, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertReturnsSetFalseVisibility()
|
||||
{
|
||||
this.converter.FalseVisibility = Visibility.Visible;
|
||||
var result = this.converter.Convert(false, null, null, null);
|
||||
Assert.AreEqual(Visibility.Visible, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBackReturnsTrueIfValueIsTrueVisibility()
|
||||
{
|
||||
this.converter.TrueVisibility = Visibility.Hidden;
|
||||
var result = this.converter.ConvertBack(Visibility.Hidden, null, null, null);
|
||||
Assert.AreEqual(true, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBackReturnsFalseIfValueIsFalseVisibility()
|
||||
{
|
||||
this.converter.FalseVisibility = Visibility.Hidden;
|
||||
var result = this.converter.ConvertBack(Visibility.Hidden, null, null, null);
|
||||
Assert.AreEqual(false, result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBackReturnsNullIfValueIsNotAVisibility()
|
||||
{
|
||||
var result = this.converter.ConvertBack(new object(), null, null, null);
|
||||
Assert.Null(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConvertBackReturnsNullIfValueIsNotAConfiguredVisibility()
|
||||
{
|
||||
var result = this.converter.ConvertBack(Visibility.Hidden, null, null, null);
|
||||
Assert.Null(result);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ScreenExtensionTests
|
||||
{
|
||||
private Screen parent;
|
||||
private Mock<IScreen> child;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.parent = new Screen();
|
||||
this.child = new Mock<IScreen>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryActivateActivatesIActivate()
|
||||
{
|
||||
var screen = new Mock<IActivate>();
|
||||
ScreenExtensions.TryActivate(screen.Object);
|
||||
screen.Verify(x => x.Activate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryActivateDoesNothingToNonIActivate()
|
||||
{
|
||||
var screen = new Mock<IDeactivate>(MockBehavior.Strict);
|
||||
ScreenExtensions.TryActivate(screen.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryDeactivateDeactivatesIDeactivate()
|
||||
{
|
||||
var screen = new Mock<IDeactivate>();
|
||||
ScreenExtensions.TryDeactivate(screen.Object);
|
||||
screen.Verify(x => x.Deactivate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryDeactivateDoesNothingToNonIDeactivate()
|
||||
{
|
||||
var screen = new Mock<IActivate>(MockBehavior.Strict);
|
||||
ScreenExtensions.TryDeactivate(screen.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryCloseClosesIClose()
|
||||
{
|
||||
var screen = new Mock<IClose>();
|
||||
ScreenExtensions.TryClose(screen.Object);
|
||||
screen.Verify(x => x.Close());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TryCloseDoesNothingToNonIClose()
|
||||
{
|
||||
var screen = new Mock<IActivate>(MockBehavior.Strict);
|
||||
ScreenExtensions.TryClose(screen.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConductWithActivates()
|
||||
{
|
||||
this.child.Object.ConductWith(this.parent);
|
||||
((IActivate)this.parent).Activate();
|
||||
this.child.Verify(x => x.Activate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConductWithDeactivates()
|
||||
{
|
||||
// Needs to be active....
|
||||
((IActivate)this.parent).Activate();
|
||||
this.child.Object.ConductWith(this.parent);
|
||||
((IDeactivate)this.parent).Deactivate();
|
||||
this.child.Verify(x => x.Deactivate());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConductWithCloses()
|
||||
{
|
||||
this.child.Object.ConductWith(this.parent);
|
||||
((IClose)this.parent).Close();
|
||||
this.child.Verify(x => x.Close());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConductWithDoesNotRetain()
|
||||
{
|
||||
var child = new Screen();
|
||||
child.ConductWith(this.parent);
|
||||
|
||||
var weakChild = new WeakReference(child);
|
||||
child = null;
|
||||
GC.Collect();
|
||||
|
||||
Assert.Null(weakChild.Target);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@
|
|||
<Compile Include="ActionExtensionTests.cs" />
|
||||
<Compile Include="AssemblySourceTests.cs" />
|
||||
<Compile Include="BindableCollectionTests.cs" />
|
||||
<Compile Include="BoolToVisibilityConverterTests.cs" />
|
||||
<Compile Include="ConductorAllActiveTests.cs" />
|
||||
<Compile Include="ConductorNavigatingTests.cs" />
|
||||
<Compile Include="ConductorOneActiveTests.cs" />
|
||||
|
@ -67,6 +68,7 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="PropertyChangedBaseTests.cs" />
|
||||
<Compile Include="PropertyChangedExtensionsTests.cs" />
|
||||
<Compile Include="ScreenExtensionTests.cs" />
|
||||
<Compile Include="ScreenTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCAutobindingTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCBindingChecksTests.cs" />
|
||||
|
@ -77,6 +79,8 @@
|
|||
<Compile Include="StyletIoC\StyletIoCGetSingleKeyedTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCGetSingleTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCUnboundGenericTests.cs" />
|
||||
<Compile Include="ViewManagerTests.cs" />
|
||||
<Compile Include="ViewTests.cs" />
|
||||
<Compile Include="WindowManagerTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
public class ViewManagerTestsViewModel
|
||||
{
|
||||
}
|
||||
|
||||
public class ViewManagerTestsView
|
||||
{
|
||||
}
|
||||
|
||||
[TestFixture, RequiresSTA]
|
||||
public class ViewManagerTests
|
||||
{
|
||||
private interface I1 { }
|
||||
private abstract class AC1 { }
|
||||
private class C1 { }
|
||||
|
||||
private class CreatingAndBindingViewManager : ViewManager
|
||||
{
|
||||
public UIElement View;
|
||||
public object RequestedModel;
|
||||
public override UIElement CreateViewForModel(object model)
|
||||
{
|
||||
this.RequestedModel = model;
|
||||
return this.View;
|
||||
}
|
||||
|
||||
public UIElement BindViewToModelView;
|
||||
public object BindViewtoModelViewModel;
|
||||
public override void BindViewToModel(UIElement view, object viewModel)
|
||||
{
|
||||
this.BindViewToModelView = view;
|
||||
this.BindViewtoModelViewModel = viewModel;
|
||||
}
|
||||
}
|
||||
|
||||
private class LocatingViewManager : ViewManager
|
||||
{
|
||||
public Type LocatedViewType;
|
||||
public override Type LocateViewForModel(Type modelType)
|
||||
{
|
||||
return this.LocatedViewType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class TestView : UIElement
|
||||
{
|
||||
public bool InitializeComponentCalled;
|
||||
public void InitializeComponent()
|
||||
{
|
||||
this.InitializeComponentCalled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private ViewManager viewManager;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.viewManager = new ViewManager();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnModelChangedDoesNothingIfNoChange()
|
||||
{
|
||||
var val = new object();
|
||||
this.viewManager.OnModelChanged(null, new DependencyPropertyChangedEventArgs(View.ModelProperty, val, val));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnModelChangedSetsNullIfNewValueNull()
|
||||
{
|
||||
var target = new ContentControl();
|
||||
this.viewManager.OnModelChanged(target, new DependencyPropertyChangedEventArgs(View.ModelProperty, 5, null));
|
||||
Assert.Null(target.Content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnModelChangedUsesViewIfAlreadySet()
|
||||
{
|
||||
var target = new ContentControl();
|
||||
var model = new Mock<IScreen>();
|
||||
var view = new UIElement();
|
||||
|
||||
model.Setup(x => x.View).Returns(view);
|
||||
this.viewManager.OnModelChanged(target, new DependencyPropertyChangedEventArgs(View.ModelProperty, null, model.Object));
|
||||
|
||||
Assert.AreEqual(view, target.Content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OnModelChangedCreatesAndBindsView()
|
||||
{
|
||||
var target = new ContentControl();
|
||||
var model = new object();
|
||||
var view = new UIElement();
|
||||
var viewManager = new CreatingAndBindingViewManager();
|
||||
|
||||
viewManager.View = view;
|
||||
|
||||
viewManager.OnModelChanged(target, new DependencyPropertyChangedEventArgs(View.ModelProperty, null, model));
|
||||
|
||||
Assert.AreEqual(viewManager.RequestedModel, model);
|
||||
Assert.AreEqual(viewManager.BindViewToModelView, view);
|
||||
Assert.AreEqual(viewManager.BindViewtoModelViewModel, model);
|
||||
Assert.AreEqual(view, target.Content);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateViewforModelThrowsIfViewNotFound()
|
||||
{
|
||||
Assert.Throws<Exception>(() => this.viewManager.LocateViewForModel(typeof(C1)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LocateViewforModelFindsViewForModel()
|
||||
{
|
||||
Execute.TestExecuteSynchronously = true;
|
||||
AssemblySource.Assemblies.Add(Assembly.GetExecutingAssembly());
|
||||
var viewType = this.viewManager.LocateViewForModel(typeof(ViewManagerTestsViewModel));
|
||||
Assert.AreEqual(typeof(ViewManagerTestsView), viewType);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateViewForModelThrowsIfViewIsNotConcreteUIElement()
|
||||
{
|
||||
var viewManager = new LocatingViewManager();
|
||||
|
||||
viewManager.LocatedViewType = typeof(I1);
|
||||
Assert.Throws<Exception>(() => viewManager.CreateViewForModel(new object()));
|
||||
|
||||
viewManager.LocatedViewType = typeof(AC1);
|
||||
Assert.Throws<Exception>(() => viewManager.CreateViewForModel(new object()));
|
||||
|
||||
viewManager.LocatedViewType = typeof(C1);
|
||||
Assert.Throws<Exception>(() => viewManager.CreateViewForModel(new object()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateViewForModelCallsFetchesViewAndCallsInitializeComponent()
|
||||
{
|
||||
var view = new TestView();
|
||||
IoC.GetInstance = (t, k) =>
|
||||
{
|
||||
Assert.AreEqual(typeof(TestView), t);
|
||||
Assert.Null(k);
|
||||
return view;
|
||||
};
|
||||
var viewManager = new LocatingViewManager();
|
||||
viewManager.LocatedViewType = typeof(TestView);
|
||||
|
||||
var returnedView = viewManager.CreateViewForModel(new object());
|
||||
|
||||
Assert.True(view.InitializeComponentCalled);
|
||||
Assert.AreEqual(view, returnedView);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreateViewForModelDoesNotComplainIfNoInitializeComponentMethod()
|
||||
{
|
||||
var view = new UIElement();
|
||||
IoC.GetInstance = (t, k) =>
|
||||
{
|
||||
Assert.AreEqual(typeof(UIElement), t);
|
||||
Assert.Null(k);
|
||||
return view;
|
||||
};
|
||||
var viewManager = new LocatingViewManager();
|
||||
viewManager.LocatedViewType = typeof(UIElement);
|
||||
|
||||
var returnedView = viewManager.CreateViewForModel(new object());
|
||||
|
||||
Assert.AreEqual(view, returnedView);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindViewToModelSetsActionTarget()
|
||||
{
|
||||
var view = new UIElement();
|
||||
var model = new object();
|
||||
this.viewManager.BindViewToModel(view, model);
|
||||
|
||||
Assert.AreEqual(model, View.GetActionTarget(view));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindViewToModelSetsDataContext()
|
||||
{
|
||||
var view = new FrameworkElement();
|
||||
var model = new object();
|
||||
this.viewManager.BindViewToModel(view, model);
|
||||
|
||||
Assert.AreEqual(model, view.DataContext);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BindViewToModelAttachesView()
|
||||
{
|
||||
var view = new UIElement();
|
||||
var model = new Mock<IViewAware>();
|
||||
this.viewManager.BindViewToModel(view, model.Object);
|
||||
|
||||
model.Verify(x => x.AttachView(view));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace StyletUnitTests
|
||||
{
|
||||
[TestFixture, RequiresSTA]
|
||||
public class ViewTests
|
||||
{
|
||||
private Mock<IViewManager> viewManager;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
this.viewManager = new Mock<IViewManager>();
|
||||
View.ViewManager = this.viewManager.Object;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ActionTargetStores()
|
||||
{
|
||||
var obj = new DependencyObject();
|
||||
View.SetActionTarget(obj, 5);
|
||||
Assert.AreEqual(5, View.GetActionTarget(obj));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ModelStores()
|
||||
{
|
||||
var obj = new DependencyObject();
|
||||
View.SetModel(obj, 5);
|
||||
Assert.AreEqual(5, View.GetModel(obj));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ChangingModelCallsOnModelChanged()
|
||||
{
|
||||
var obj = new DependencyObject();
|
||||
var model = new object();
|
||||
View.SetModel(obj, null);
|
||||
|
||||
DependencyPropertyChangedEventArgs ea = default(DependencyPropertyChangedEventArgs);
|
||||
this.viewManager.Setup(x => x.OnModelChanged(obj, It.IsAny<DependencyPropertyChangedEventArgs>()))
|
||||
.Callback<DependencyObject, DependencyPropertyChangedEventArgs>((d, e) => ea = e).Verifiable();
|
||||
View.SetModel(obj, model);
|
||||
|
||||
this.viewManager.Verify();
|
||||
Assert.Null(ea.OldValue);
|
||||
Assert.AreEqual(model, ea.NewValue);
|
||||
Assert.AreEqual(View.ModelProperty, ea.Property);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void SetsContentControlContentProperty()
|
||||
{
|
||||
var obj = new ContentControl();
|
||||
var view = new UIElement();
|
||||
|
||||
View.SetContentProperty(obj, view);
|
||||
Assert.AreEqual(obj.Content, view);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue