5

我有一个标签控件,它有 3 个标签页。在同一表单/视图上的此选项卡控件下方,我有 3 个图像控件。

基于选项卡的 SelectedIndex,我需要更改以下 3 张图像的不透明度。

截至目前,我在 Tab 控件的 SelectionChanged 事件中有类似的内容:

switch (Tab.SelectedIndex)
{
     case 0:
         img1.Opacity= 1;
         img2.Opacity = 0.5;
         img3.Opacity  = 0.5;
         break;
     case 1:
         img1.Opacity = 0.5;
         img2.Opacity = 1;
         img3.Opacity  = 0.5;
         break;
     case 2:
         img1.Opacity = 0.5;
         img2.Opacity = 0.5;
         img3.Opacity = 1;
         break;
}

如何删除此 switch 语句?我应该在这里使用哪种设计模式?

4

6 回答 6

1

您可以使用此处为实例解释的 State 设计模式。您将定义几个状态,然后根据条件决定当前应该使用哪些状态。

例子:

abstract class State
{
    abstract vod Apply(Form context);
}

class StateOne : State
{
    override void Apply(Form context)
    {
        img1.Opacity= 1;
        img2.Opacity = 0.5;
        img3.Opacity  = 0.5;
    }
}

您还可以将它与决定使用哪种状态的工厂方法设计模式结合起来。

static class StateFactory
{
    static State GetState(condition)
    {
        if(condition == something)
            return new StateOne();
        else ...
    }
}

这不会从您的代码中删除 switch 语句,但它至少会在一个合理的地方做合理的事情。

用法:

StateFactory.GetState(condition).Apply(this);
于 2013-09-22T17:55:29.653 回答
1

提取和注入。将视图更改逻辑(切换)提取到外部类/方法并将其注入您的视图:

public void HighlightImages(int selection, params Image[] images)
{
    switch (selection)
    {
        case 0:
            images[0].Opacity= 1;
            images[1].Opacity = 0.5;
            images[2].Opacity  = 0.5;
            break;
        case 1:
            images[0].Opacity = 0.5;
            images[1].Opacity = 1;
            images[2].Opacity  = 0.5;
            break;
        case 2:
            images[0].Opacity = 0.5;
            images[1].Opacity = 0.5;
            images[2].Opacity = 1;
            break;
    }
}

在选择更改处理程序中,您只需将处理委托给注入的依赖项:

private void SelectedIndexChanged(object sender, EventArgs e)
{
    this.highlighter.HighlightImages(Tab.SelectedIndex, img1, img2, img3);
}

这样,您应该能够轻松地测试不透明度更改逻辑,而无需实例化完整的视图控件。

于 2013-09-22T18:05:59.583 回答
1

我认为你可以在你的 xaml 中使用Triggers.

此外,如果您希望此单元可测试,您应该使用MVVM pattern您将在其中定义properties for SelectedIndex, Opacities的位置ViewModel并将它们绑定到 xaml

于 2013-09-22T17:55:37.113 回答
0

参考“jimmy-keen”所说的话,这就是我想要的:

    public static void HighlightImages(int selection, params Image[] images)
    {
        for (int img = 0; img < images.Length; img++)
        {
            images[img].Opacity = (img == selection ? 1 : 0.5);
        }
    }
于 2013-09-22T19:56:28.293 回答
0

这不会完全删除它,因为除了创建一个大类遗产之外没有什么可做的,但这对于这种情况来说有点过分了。

相反,您可以像这样减小它的大小:

switch (Tab.SelectedIndex)
{
     img1.Opacity = 0.5;
     img2.Opacity = 0.5;
     img3.Opacity = 0.5;

     case 0:
         img1.Opacity += 0.5;
         break;
     case 1:
         img2.Opacity += 0.5;
         break;
     case 2:
         img3.Opacity += 0.5;
         break;
}

并且您可以通过方法减少代码冗余,因此您不必在每次要更改不透明度时到处更改 0.5。(把 0.5 放在一个常数中也很好):

switch (Tab.SelectedIndex)
{
     SetInitialOpacity(img1);
     SetInitialOpacity(img2);
     SetInitialOpacity(img3);

     case 0:
         IncreaseOpacity(img1);
         break;
     case 1:
         IncreaseOpacity(img2);
         break;
     case 2:
         IncreaseOpacity(img3);
         break;
}

private void SetInitialOpacity(Image image)
{
    image.Opacity = 0.5;
}


private void IncreaseOpacity(Image image)
{
    image.Opacity += 0.5;
}
于 2013-09-22T18:12:41.063 回答
0

如果您有一堆需要传入的任意数据......那么真的没有办法轻松绕过 switch 语句(至少值得付出努力)。我建议,至少在代码可读性方面,使用枚举。您可以像这样重构您的代码:

    switch ((ImageTypes)Tab.SelectedIndex)
    {
        case ImageTypes.TypeOne:
            img1.Opacity= 1;
            img2.Opacity = 0.5;
            img3.Opacity  = 0.5;
            break;
        case ImageTypes.TypeTwo:
            img1.Opacity = 0.5;
            img2.Opacity = 1;
            img3.Opacity  = 0.5;
            break;
        case ImageTypes.TypeThree:
            img1.Opacity = 0.5;
            img2.Opacity = 0.5;
            img3.Opacity = 1;
            break;
    }
    public enum ImageTypes
    {
        TypeOne,
        TypeTwo,
        TypeThree
    }
于 2013-09-22T17:58:15.733 回答