Как можно сократить подобный код или вовсе от него избавится?

196
12 июля 2017, 22:17

Имею ряд кнопок, которые переключают страницу приложения. У кнопок есть 2 состояния, нажатая и нет, для каждого состояния реализован стиль Menu - обычная и MenuIn - нажатая (то есть у пользователя открыта сейчас именно эта страница). В стилях изменяется только цвет.

Сейчас у меня каждая кнопка привязана к обработчику, который с помощью switch, по названию кнопки выполняет необходимые действия, а именно открывает нужную страницу, задает всем не активным кнопкам стиль Menu и кнопке текущего раздела задает стиль MenuIn. В итоге у меня получается огромная портянка повторяющихся строк.

Как грамотно сократить код, может в стиле как то определять нажата кнопка или нет, может еще что?

private void ButtonEvent(string name)
        {
            switch (name)
            {
                case "ChangeBg":
                    BackgroundEvent.Restart();
                    break;
                case "HomeBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    MainFrame.Navigate(new Uri("View/HomePage.xaml", UriKind.Relative));
                    break;
                case "NewsBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //MyPopup.IsOpen = true;
                    MainFrame.Navigate(new Uri("View/NewsPage.xaml", UriKind.Relative));
                    break;
                case "AlertsBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //MyPopup.IsOpen = false;
                    //BodyFrame.Navigate(new Uri("Pages/AlertsPage.xaml", UriKind.Relative));
                    break;
                case "TradeBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //BodyFrame.Navigate(new Uri("Pages/TradePage.xaml", UriKind.Relative));
                    break;
                case "InvasionsBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //BodyFrame.Navigate(new Uri("Pages/InvasionsPage.xaml", UriKind.Relative));
                    break;
                case "InfoBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //BodyFrame.Navigate(new Uri("Pages/InfoPage.xaml", UriKind.Relative));
                    break;
                case "SettingsBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    //BodyFrame.Navigate(new Uri("Pages/SettingsPage.xaml", UriKind.Relative));
                    break;
                case "ActMissionsBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
                    SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
                    TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    //BodyFrame.Navigate(new Uri("Pages/ActiveMissionsPage.xaml", UriKind.Relative));
                    break;
            }
        }

Answer 1

Это выглядит неправильно семантически.

Во-первых, каждая кнопка должна быть ответственна за себя, посторонний код не должен быть нужен.

Затем, скорее всего у вас не должно быть разных стилей для разных состояний кнопки. Для того, чтобы поменять изображение, просто примените триггер. Нужные куски информации для триггера положите в attached property.

В результате получится что-то такое

<Style TargetType="ToggleButton" x:Key="MenuButton">
    <Setter Property="Width" Value="24"/> <!-- или сколько там надо -->
    <!-- остальные свойства -->
    <Style.Triggers>
        <Trigger Property="IsChecked" Value="True">
            <Setter Property="Background" Value="Pink"/>
            <!-- и так далее -->
        </Trigger>
    </Style.Triggers>
</Style>

Необходимость в ButtonEvent отпадает.

Для того, чтобы набор ToggleButton'ов вёл себя как RadioButton'ы, можно взять RadioButton'ы и застилизовать их:

<Grid>
    <Grid.Resources>
        <Style TargetType="ToggleButton" x:Key="MenuButton"
               BasedOn="{StaticResource {x:Type ToggleButton}}">
            <Setter Property="Width" Value="30"/>
            <Setter Property="Height" Value="30"/>
            <!-- остальная часть стиля -->
        </Style>
    </Grid.Resources>
    <StackPanel Orientation="Vertical" Width="30">
        <RadioButton Style="{StaticResource MenuButton}" GroupName="First"/>
        <RadioButton Style="{StaticResource MenuButton}" GroupName="First"/>
        <RadioButton Style="{StaticResource MenuButton}" GroupName="First"/>
        <Grid Height="10"/>
        <RadioButton Style="{StaticResource MenuButton}" GroupName="Second"/>
        <RadioButton Style="{StaticResource MenuButton}" GroupName="Second"/>
        <RadioButton Style="{StaticResource MenuButton}" GroupName="Second"/>
    </StackPanel>
</Grid>

Чтобы привязать команды к каждой кнопке, я бы сделал так. Во-первых, в DataContext'е (то есть, VM) положил бы коллекцию команд.

Вместо ручного создания кнопок взял бы ItemsControl:

<ItemsControl ItemsSource="{Binding Commands}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Vertical"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <RadioButton Style="{StaticResource MenuButton}" GroupName="First"
                         Command="{Binding}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

По нажатию кнопки вызывалась бы команда, а она уж пусть решает, что делать дальше.

Если ваш контрол — на самом деле ToolBar, вы можете использовать ToolBar вместо ItemsControl'а.

<ToolBarTray Orientation="Vertical">
    <ToolBar ItemsSource="{Binding Commands}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <RadioButton Style="{StaticResource MenuButton}" GroupName="First"
                             Command="{Binding}"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ToolBar>
</ToolBarTray>
Answer 2

Можно попробовать засунуть все кнопки в коллекцию myButtons, тогда получается что-то вроде:

private void ButtonEvent(string name)
{
    if (name == "ChangeBg")
    {
        BackgroundEvent.Restart()
        return;
    }
    var myButtons = new[] { HomeBtn, NewsBtn, AlertsBtn, InvasionsBtn,
                            SettingsBtn, InfoBtn, TradeBtn, ActMissionsBtn };
    foreach(var element in myButtons)
    {
        if (element.Name == name)
            element.Style = (Style) Application.Current.Resources["MenuIn"];
        else
            element.Style = (Style) Application.Current.Resources["Menu"];
    }
    BodyFrame.Navigate(new Uri("Pages/" + name.Substring(0, name.Length - 3) + "Page.xaml", UriKind.Relative));
}

UPD: Как правильно заметил @Андрей, было бы намного лучше где-нибудь написать что-то вроде:

readonly Style MenuInStyle = (Style) Application.Current.Resources["MenuIn"];
readonly Style MenuStyle = (Style) Application.Current.Resources["Menu"]

Тогда код становится понятнее:

private void ButtonEvent(string name)
{
    if (name == "ChangeBg")
    {
        BackgroundEvent.Restart()
        return;
    }
    var myButtons = new[] { HomeBtn, NewsBtn, AlertsBtn, InvasionsBtn,
                            SettingsBtn, InfoBtn, TradeBtn, ActMissionsBtn };
    foreach(var element in myButtons)
    {
        if (element.Name == name)
            element.Style = MenuInStyle;
        else
            element.Style = MenuStyle;
    }
    BodyFrame.Navigate(new Uri("Pages/" + name.Substring(0, name.Length - 3) + "Page.xaml", UriKind.Relative));
}
Answer 3
private void ButtonEvent(string name)
        {
            HomeBtn.Style = (Style) Application.Current.Resources["Menu"];
            NewsBtn.Style = (Style) Application.Current.Resources["Menu"];
            AlertsBtn.Style = (Style) Application.Current.Resources["Menu"];
            InvasionsBtn.Style = (Style) Application.Current.Resources["Menu"];
            SettingsBtn.Style = (Style) Application.Current.Resources["Menu"];
            InfoBtn.Style = (Style) Application.Current.Resources["Menu"];
            TradeBtn.Style = (Style) Application.Current.Resources["Menu"];
            ActMissionsBtn.Style = (Style) Application.Current.Resources["Menu"];
            switch (name)
            {
                case "ChangeBg":
                    BackgroundEvent.Restart();
                    break;
                case "HomeBtn":
                    HomeBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    MainFrame.Navigate(new Uri("View/HomePage.xaml", UriKind.Relative));
                    break;
                case "NewsBtn":
                    NewsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    MainFrame.Navigate(new Uri("View/NewsPage.xaml", UriKind.Relative));
                    break;
                case "AlertsBtn":
                    AlertsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/AlertsPage.xaml", UriKind.Relative));
                    break;
                case "TradeBtn":
                    TradeBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/TradePage.xaml", UriKind.Relative));
                    break;
                case "InvasionsBtn":
                    InvasionsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/InvasionsPage.xaml", UriKind.Relative));
                    break;
                case "InfoBtn":
                    InfoBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/InfoPage.xaml", UriKind.Relative));
                    break;
                case "SettingsBtn":
                    SettingsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/SettingsPage.xaml", UriKind.Relative));
                    break;
                case "ActMissionsBtn":
                    ActMissionsBtn.Style = (Style) Application.Current.Resources["MenuIn"];
                    BodyFrame.Navigate(new Uri("Pages/ActiveMissionsPage.xaml", UriKind.Relative));
                    break;
            }
        }

(Update) А вот такой пример подойдет?

private void ButtonEvent(string name)
        {
            if (name == "ChangeBg") {
                BackgroundEvent.Restart();
                return;
            }
            HomeBtn.Style = (Style) Application.Current.Resources[name != "HomeBtn" ? "Menu" : "MenuIn"];
            NewsBtn.Style = (Style) Application.Current.Resources[name != "NewsBtn" ? "Menu" : "MenuIn"];
            AlertsBtn.Style = (Style) Application.Current.Resources[name != "AlertsBtn" ? "Menu" : "MenuIn"];
            InvasionsBtn.Style = (Style) Application.Current.Resources[name != "InvasionsBtn" ? "Menu" : "MenuIn"];
            SettingsBtn.Style = (Style) Application.Current.Resources[name != "SettingsBtn" ? "Menu" : "MenuIn"];
            InfoBtn.Style = (Style) Application.Current.Resources[name != "InfoBtn" ? "Menu" : "MenuIn"];
            TradeBtn.Style = (Style) Application.Current.Resources[name != "TradeBtn" ? "Menu" : "MenuIn"];
            ActMissionsBtn.Style = (Style) Application.Current.Resources[name != "ActMissionsBtn" ? "Menu" : "MenuIn"];
            BodyFrame.Navigate(new Uri("Pages/" + name.Substring(0, name.Length - 3) + "Page.xaml", UriKind.Relative));
        }
READ ALSO
как получить длступ к xaml из своего класса?

как получить длступ к xaml из своего класса?

Как получить доступ элементам MainPagexaml из созданного мной класса?

165
Почему Bower выдает ошибку &ldquo;throw error;&rdquo;?

Почему Bower выдает ошибку “throw error;”?

У меня есть проект, который находиться на диске "E" и bower работает отлично

281
Как отфильтровать массив объектов?

Как отфильтровать массив объектов?

В filterArraystatus_id при выборе двух одинаковых статусов падают одинаковые объекты

297
Доступ к компонентам react

Доступ к компонентам react

Как можно протестировать react компонент, пытаюсь создать класс things который наследуется от const MapServ, нет доступа к testMethod , getPage ни в переменной...

271