返回首页

简介
最近,我已经工作了很多Silverlight项目。它们之间的共同点是,他们都是一堆的UserControls彼此之间导航。例如,第一个控制将Login.xaml,一旦通过验证,就需要导航到主应用程序。然后主应用程序的导航部分(如菜单等),将电流控制,这可能需要导航到另一个侧面。依此类推。
那么,已经为我工作出色,是创建一个UserControl作为页面控制器,并转换和加载,需要做的一切。您只需通过一个UIElement(这将是一个几乎在每一种情况的UserControl),加载它,然后替换目前在屏幕上。使用代码创建一个新的Silverlight应用程序项目或去一个现有的。将所有的导航控制一个UserControl的。所以称为NavController.xaml项目添加一个新的UserControl。NavController.xaml将有一个主电网(LayoutRoot的),然后把里面将一个边界(ControlContainer)以上,将原有的控制(ImageOverlay)(后来),然后一个灰色的叠加(GrayOverlay ),比,最后一个swirly装载机(装载机)。
{S0}
为该XAML - ,你应该投入NavController.xaml - 看起来像这样:

<Grid x:Name="LayoutRoot">

    <Border x:Name="ContentContainer" 

       VerticalAlignment="Stretch" HorizontalAlignment="Stretch">

    </Border>

    <Image Opacity="0" x:Name="ImageOverlay" 

          VerticalAlignment="Stretch" 

          HorizontalAlignment="Stretch" />

    <Rectangle Opacity="0" x:Name="GrayOverlay" 

            VerticalAlignment="Stretch" 

            HorizontalAlignment="Stretch">

        <Rectangle.Fill>

            <RadialGradientBrush>

                <GradientStop Color="#55000000" Offset="0" />

                <GradientStop Color="#C5000000" Offset="1" />

            </RadialGradientBrush>

        </Rectangle.Fill>

    </Rectangle>

    <Border Opacity="0" VerticalAlignment="Center" 

        HorizontalAlignment="Center" x:Name="Loader"></Border>

</Grid>
现在进入NavController.cs。我们需要一个方法,它接受一个UIElement,并涉及到在屏幕上的所有工作。这里会发生什么事击穿:该方法传递一个UIElement。我们采取了什么是目前屏幕上的截图和显示,在ImageOverlay控制。显示ImageOverlay,GrayOverlay和Loader控制。更换新的UIElement ContentContainer.Child。在新的控制Loaded事件,调用另一个NavController方法隐藏从第3步控制。
现在一个约2和第5步快速解释:我们可能只需更换新的控制而不做图像ContentContainer孩子,但然后,用户将看到改变(像闪烁)的控制,不会看无缝在所有。因此,我们需要它的屏幕截图显示,新的控制,然后可以在其所有加载的背景。例如,新的控制可调用Web服务,并需要几秒钟加载。这很好,是因为一旦所有的初始加载控制,它会调用加载停止。或者有没有服务调用,它可以设置加载停止Loaded事件。
因此,首先,我们需要创建故事板显示和隐藏这些控件,从第3步。我做一个简单的淡入淡出效果,但你真的可以做任何事情。
这将大大低于上述电网年底:{C}
我们的方法做的第一件事是设置一个类变量,通过控制,使我们可以用它完成一次显示动画。下一步,我们采取了ContentContainer元素使用WritableBitmap的截图(这不是技术上是正确的,但你明白我的意思)。然后我们设置ImageOverlay控制该图像的来源,然后显示所有覆盖(虽然他们的不透明仍是0,所以他们将不会看到),终于开始动画褪色覆盖英寸
private UIElement _waitingControl = null;



public void NavigateToControl(UIElement newControl)

{

    _waitingControl = newControl;

    //take screenshot

    WriteableBitmap bitmap = new WriteableBitmap(ContentContainer, null);

    ImageOverlay.Source = bitmap;//set the source of the image control

    bitmap.Invalidate();//kill the bitmap

    ImageOverlay.Visibility = System.Windows.Visibility.Visible; 

    GrayOverlay.Visibility = System.Windows.Visibility.Visible;

    Loader.Visibility = System.Windows.Visibility.Visible;

    DisplayOverlays.Begin();

}

和方法来隐藏覆盖(将得到一次完成它所需要的新的控制称为是不言自明):
public void Hide()

{

    HideOverlays.Begin();

    //start hiding all the overlays to display the new control

}

当完成覆盖动画的衰落是我们隐藏了底层控制,那么我们可以改变它的新的控制(用户将不会看到,因为覆盖的):
private void DisplayOverlays_Completed(object sender, EventArgs e)

{

    ContentContainer.Child = _waitingControl;

    // change the control to the new one

}

一旦覆盖已隐藏(在其不透明度方面),我们需要他们崩溃。这是因为,即使他们是透明的,你将不能够通过点击。
private void HideOverlays_Completed(object sender, EventArgs e)

{

    ImageOverlay.Visibility = System.Windows.Visibility.Collapsed; 

    GrayOverlay.Visibility = System.Windows.Visibility.Collapsed;

    Loader.Visibility = System.Windows.Visibility.Collapsed;

}
好了,现在基本上是这样做的实际控制,我们需要为任何控制方式可以调用它的父NavController。为此,我们将有一个全球性的静态类中有一些聪明的方法。添加一个新的类Global.cs。在此,把这个:
public static class Global

{

    public static T FindParent<T>(UIElement control) where T : UIElement

    {

        UIElement p = VisualTreeHelper.GetParent(control) as UIElement;

        if (p != null)

        {

            if (p is T)

                return p as T;

            else

                return FindParent<T>(p);

            }

            return null;

        }

 

        public static void ChangeControl(this UIElement uc, UIElement newControl)

        {

            NavController controller = FindParent<NavController>(uc);

 

            if (controller != null)

                controller.NavigateToControl(newControl);

        }

 

        public static void HideLoading(this UIElement uc)

        {

            NavController controller = FindParent<NavController>(uc);



            if (controller != null)

                controller.Hide();

        }

}

第一部分是一个非常有用的helper方法,这将导航可视化树,并返回该类型的一审。因此,我们将使用它,可以找到任何控制,它是在第一NavController。这两种方法后,可以更容易地停止装货或从任何UIElement导航到一个新的控制。注意在参数列表中的this?这意味着任何UIElement上,我们现在可以做:myElement.HideLoading();酷吧?请记住,这两个方法调用他们在NavController对口,但必须是不一样的的名称,否则就会导致一个无限循环,并可能破坏宇宙。我们正在接近它的工作的!但首先,我们需要设置我们的新NavController,成为第一个控制被载入(然后事情会内的负载)。所以开放App.cs找到Application_Startup方法。替换当前行与此有:
this.RootVisual = new NavController(); 

(this.RootVisual as NavController).NavigateToControl(new Login()); 

第一行第一次被载入,NavController控制。然后运行下一行告诉它改变到一个新的控制方法。在这种情况下,我刚刚创建一个UserControl所谓的登录,这将是登录。
确定,现在如前面提到的,这种方式必须告诉NavController停止加载时,它是每一个被载入的控制。在登录的情况下,将完成这样的加载控制时:
public Login()

{

    InitializeComponent();

    this.Loaded += (se, ev) =>

        {

            this.HideLoading();

        };

}

,然后当用户点击按钮,可以切换到这样一个新的控制(在这种情况下,回主页):
private void Button_Click(object sender, RoutedEventArgs e)

{

    //check login etc

    this.ChangeControl(new MainPage());

}
结束语
下载包含以上解释的是什么,再加上一些控制,以更好地解释。它还演示了如何你可以有一个在另一个NavController。我会尽快作出swirly装载机另一篇文章 - 但你可以把你想要Loader控制。你可以尝试下面的解决方案。请注意
我想欣赏评论 - 但要记住,这是我的第一篇文章,所以不要过分计较:P
,您可以查看原来的职位,并在我的博客查看演示在这里:{A}。历史2011年2月18日 - 写成文章。

回答

评论会员:P 时间:2