Ответы пользователя по тегу WPF
  • Не срабатывает свойство в WPF. В чём ошибка?

    SpacePurr
    @SpacePurr
    c#, wpf
    Вместо StackPanel используйте DockPanel
    <DockPanel>
         <Label Content="Фамилия:"/>
         <TextBox Width="300" />
    </DockPanel>


    Для StackPanel стиль убирайте, для TextBox оставляйте.
    5e7affefc3b9f806003549.png
    Ответ написан
  • Можно ли во ViewModel узнать ширину элемента View?

    SpacePurr
    @SpacePurr
    c#, wpf
    Не знаю насколько это противоречит паттерну, но с ходу пришло такое решение.

    View:
    <Button x:Name="MyButton" Command="{Binding ClickCommand}" 
    CommandParameter="{Binding ElementName=MyButton}"/>


    ViewModel:
    public class MainViewModel : BaseViewModel
    {
        public Command ClickCommand { get; set; }
    
        public MainViewModel()
        {
            ClickCommand = new Command(ClickCommandExecute);
        }
    
        private void ClickCommandExecute(object obj)
        {
            Button button = obj as Button;
            MessageBox.Show(button.ActualHeight.ToString() + " : " + button.ActualWidth);
        }
    }


    Только тсссссс! ViewModel ни слова!
    Ответ написан
  • Почему из SelectedItem Listbox я получаю предыдущий выбранный элемент?

    SpacePurr
    @SpacePurr
    c#, wpf
    Я не эксперт, но возможно событие GotFocus срабатывает раньше, чем присваивается значение выделенному элементу SelectedItem.

    Решить можно так.

    Помимо библиотеки interactivity подключите библиотеку interactions:
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:ei ="http://schemas.microsoft.com/expression/2010/interactions"


    Подключение события будет выглядеть вот так:
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="GotFocus">
            <ei:CallMethodAction MethodName="NoteList_GotFocus"
                                 TargetObject="{Binding }"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>


    ViewModel:
    public void NoteList_GotFocus(object sender, RoutedEventArgs e)
    {
        if (e.OriginalSource is ListBoxItem lvi)
        {
            Note note = lvi.DataContext as Note;
            MessageBox.Show(note.Title);
        }
    }


    Доказательство:
    5dfc71a903242851876417.gif
    Ответ написан
  • Как сделать binding текста из textbox в label?

    SpacePurr
    @SpacePurr
    c#, wpf
    В конструктор второго окна передавайте Text из основного окна и присваивайте нужному Label.
    Например так:
    public partial class SecondWindow: Window
    {
        public SecondWindow(string text)
        {
            InitializeComponent();
            CategoryText.Text = text;
        }
    }


    SecondWindow window = new SecondWindow(CategoryLabel1.Text);


    Если используете MVVM, то передавайте свойство в ViewModel второго окна.
    Ответ написан
  • Как создать инсталятор для WPF приложения?

    SpacePurr
    @SpacePurr
    c#, wpf
    Не обязательно использовать инсталлятор встроенный.
    Попробуйте Smart Install Maker, достаточно гибкая программа.
    Ответ написан
  • Как перенести метод для кнопок в отдельный класс в WPF?

    SpacePurr
    @SpacePurr
    c#, wpf
    Вам не нужно переносить методы. Просто опишите их в нужном вам классе и вызовите в методах в классе окна.

    Например так:
    public partial class MainWindow : Window
        {
            Animation animation;
    
            bool isOptionsOpen1 = false;
            bool isOptionsOpen2 = false;
    
            public MainWindow()
            {
                InitializeComponent();
                HotKeys hk = new HotKeys(this);
                animation = new Animation(this);
            }               
    
            private void OpenOptions(object sender, RoutedEventArgs e)
            {             
               animation.OpenOptions();
            }
    
            private void HideOptions(object sender, RoutedEventArgs e)
            {           
               animation.HideOptions();
            }
        }
    Ответ написан
  • Прозрачность окон в wpf?

    SpacePurr
    @SpacePurr
    c#, wpf
    Добавьте свойство AllowTransparency = "True" и WindowsStyle = "None"
    <Window x:Class="WpfApp1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="MainWindow" Height="450" Width="800" Opacity="0.5" AllowsTransparency="True" 
            WindowStyle="None">
    Ответ написан
  • Как деактивировать все toggle button кроме одного при клике?

    SpacePurr
    @SpacePurr
    c#, wpf
    Определите такой стиль
    <Window.Resources>
        <Style TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <ToggleButton IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                            Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>


    Теперь просто объявите нужное количество RadioButton
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
    
        <RadioButton Grid.Column="0" Width="50" Height="50" />
        <RadioButton Grid.Column="1" Width="50" Height="50" />
        <RadioButton Grid.Column="2" Width="50" Height="50" />
    </Grid>


    При нажатии на кнопку только она становится активной. При повторном нажатии на нее она становится неактивной.

    5de755219b192060452254.gif

    Также, если вы хотите сделать группы таких кнопок, вам нужно добавить к RadioButton свойство GroupName с именем группы.
    <RadioButton GroupName="Group1"/>
    <RadioButton GroupName="Group1"/>
    <RadioButton GroupName="Group1"/>
    
    <RadioButton GroupName="Group2"/>
    <RadioButton GroupName="Group2"/>
    <RadioButton GroupName="Group2"/>


    Тогда нажатие на кнопку из Group1 никак не будет влиять на кнопки из Group2.
    Ответ написан
  • Как получить доступ к главному окну из другого класса в WPF?

    SpacePurr
    @SpacePurr
    c#, wpf
    Передача this в конструктор нового класса.

    class HotKeys
    {
         private MainWindow window;
         //Конструктор
         public HotKeys(MainWIndow _window)
         {
              window = _window;
         }
    }


    namespace Toolkits
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
           
            public MainWindow()
            {
                InitializeComponent();
                HotKeys hk = new HotKeys(this);           
            }
        }
    }
    Ответ написан
  • Как вызывать одно и тоже контекстное меню для каждого элемента с одинаковым типом?

    SpacePurr
    @SpacePurr
    c#, wpf
    Возможно вам подойдет такой вариант:
    <Window.Resources>
        <ContextMenu x:Key="MyContextMenu">
            <!--Ваше меню -->
        </ContextMenu>
    </Window.Resources>
    
    <Grid>
         <!-- колонки строки -->
        <TextBox Tag="1" Grid.Column="1" Grid.Row="5" ContextMenu="{StaticResource MyContextMenu}"/>        
        <TextBox Tag="2" Grid.Column="2" Grid.Row="5" ContextMenu="{StaticResource MyContextMenu}"/>                   
    </Grid>
    Ответ написан
  • Как открыть форму по нажатию на строку в DataGrid?

    SpacePurr
    @SpacePurr
    c#, wpf
    • Создаем колонку, содержимое в ячейках которой будет представлять Button с событием Button_Click.
      <DataGrid Name="MyDataGrid" ItemsSource="{Binding Table}">
          <DataGrid.Columns>
              <DataGridTemplateColumn>
                  <DataGridTemplateColumn.CellTemplate>
                      <DataTemplate>
                          <Button Click="Button_Click">Open Form</Button>
                      </DataTemplate>
                  </DataGridTemplateColumn.CellTemplate>
              </DataGridTemplateColumn>
          </DataGrid.Columns>
      </DataGrid>

    • Пусть имеется некая форма TosterForm, конструктор которой принимает один строковый аргумент - значение в 3 колонке выделенной строки.
      private void Button_Click(object sender, RoutedEventArgs e)
      {
          TosterForm form = new TosterForm(((DataRowView)MyDataGrid.SelectedItem).Row.ItemArray[3].ToString());
          form.ShowDialog();
      }

      По поводу получения значения в ячейке может есть и другой вариант, я до этого практически не работал с DataGrid.


    Собственно, вроде все.
    5dc1d8876549f349153436.gif
    Ответ написан
  • Как создать собственную библиотеку?

    SpacePurr
    @SpacePurr Автор вопроса
    c#, wpf
    Вопрос не имеет особого смысла. Закрыто)
    Ответ написан
  • Как удалить выбранную строку в Datagrid?

    SpacePurr
    @SpacePurr
    c#, wpf
    DataTable Table{get; set;}
    DataAdapter dataAdapter;
    
    private void DeleteMethod(object obj)
    {
    
        var indexDataTable= //получаете здесь индекс из колонки "индекс"(например) выбранной строки
        var indexDataGridRow = //тут индекс самой строки, чтобы удалить ее из DataTable, либо вообще DataTable заново получать
    
        using (SqlCommand cmd = new SqlCommand())
        {
            cmd.Connection = new SqlConnection(connectionString);
            cmd.CommandText = "DELETE FROM YourTableName where id=" + indexDataTable;
    
            cmd.Connection.Open();
            cmd.ExecuteNonQuery();
            cmd.Connection.Close();
        }
    
        Table.Rows[indexDataGridRow].Delete();
        Table.AcceptChanges();
        dataAdapter.Update(Table);
    }
    Ответ написан
  • Как переключаться между окнами в WPF с паттерном MVVM?

    SpacePurr
    @SpacePurr
    c#, wpf
    Попробуйте посмотреть здесь Ссылка

    p.s.
    Я сейчас сам изучаю шарп, пишу небольшую программу для работы с Компас 3Д и тоже столкнулся с реализацией открытия новых окон на MVVM, однако ради одного окна я не стал надолго уходить в изучение сервисов навигации и просто создал объект нужного окна в MainViewModel и вызвал у него ShowDialog(), а NewViewModel нового окна привязана к View через DataContext как обычно это делается.
    NewWindow window = new NewWindow();
    window.ShowDialog();

    Для обмена информацией между разными VIewModel использую классы со статическими конструкциями.

    Удачи в изучении.
    Ответ написан
  • Как изменить фон у button по Click при реализованном новом шаблоне?

    SpacePurr
    @SpacePurr Автор вопроса
    c#, wpf
    Вопрос решен использованием {Binding MyVarName} и реализацией MyVarName переменной в Code Behind с реализованным интерфейсом INotifyPropertyChanged .
    Binding работает как в Border так и в Trigger.
    Все изменяется динамически в процессе работы программы (написал тестовое окно с двум полями, куда вводил HEX цвет, все отлично работает).
    Binding не работает в ColorAnimation. Для передачи цвета в анимацию, аргумент должен быть "замороженным". Однако эта проблема также решаема созданием своего класса Button, наследуемого от FrameworkElement, но для меня это пока дебри.

    Итого:
    1. Реализация линейного градиента
    2. Реализация градиентной зацикленной анимации при наведении
    3. Реализация радиальной заливки при нажатии
    4. Динамическая смена цвета градиента

    XAML:
    <Window x:Class="SxApp.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:SxApp"
            mc:Ignorable="d"
            Title="Aesthetic" Height="450" Width="450">
    
    
        <Window.Background>
            <ImageBrush 
                ImageSource="/SxApp;component/images/bck.jpg" Stretch="UniformToFill"/>
        </Window.Background>
    
    
        <Window.Resources>
            <Color x:Key="vapor_1">#db2525</Color>
            <Color x:Key="vapor_2">#a944ff</Color>
            <Color x:Key="vaporBorder">#8c5791</Color>
            <Color x:Key="vaporLime">#32CD32</Color>
            
            
            <ControlTemplate x:Key="ButtonTemplate"
                             TargetType="Button">
                <Border x:Name="Border"
                        CornerRadius="2000" 
                        TextBlock.Foreground="pink"
                        TextBlock.FontSize="23"
                        TextBlock.FontStyle="Italic"
                        TextBlock.FontWeight="Bold"
                        Margin="10"
                        >
                    <Border.Background >
                        <LinearGradientBrush>
                            <GradientStopCollection>
                                <GradientStop Offset="0" Color="{Binding ButtonColor1}"/>
                                <GradientStop Offset="1" Color="{Binding ButtonColor2}"/>
                            </GradientStopCollection>
                        </LinearGradientBrush>
                    </Border.Background>
    
                    <ContentPresenter
                        RecognizesAccessKey="True"
                        VerticalAlignment="Center"
                        HorizontalAlignment="Center"
                        />
                </Border>
    
                <ControlTemplate.Triggers>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="Border" Property="Background">
                            <Setter.Value>
                                <RadialGradientBrush>
                                    <GradientStop Color="{Binding ButtonPressColor1}" Offset="1" />
                                    <GradientStop Color="{Binding ButtonPressColor2}" Offset="0.2" />
                                </RadialGradientBrush>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
    
                    <EventTrigger RoutedEvent="MouseEnter">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty=
                                                "Background.GradientStops[0].Color" 
                                                To="{StaticResource vapor_2}" Duration="0:0:1"
                                                AutoReverse="True"
                                                RepeatBehavior="Forever">
                                </ColorAnimation>
    
                                <ColorAnimation Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="Background.GradientStops[1].Color" 
                                                To="{StaticResource vapor_1}" Duration="0:0:1"
                                                AutoReverse="True"
                                                RepeatBehavior="Forever">
                                </ColorAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
    
                    <EventTrigger RoutedEvent="MouseLeave">
                        <BeginStoryboard>
                            <Storyboard>
                                <ColorAnimation Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="Background.GradientStops[0].Color" 
                                                Duration="0:0:1">
                                </ColorAnimation>
    
                                <ColorAnimation Storyboard.TargetName="Border"
                                                Storyboard.TargetProperty="Background.GradientStops[1].Color" 
                                                Duration="0:0:1">
                                </ColorAnimation>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Window.Resources>
        
        
        <Grid>
            <Button
                Name="aesButton"
                Click="AesButton_Click"
                Content="Aesthetic"
                Width="200"
                Height="200"
                Template="{StaticResource ButtonTemplate}"/>
        </Grid>
    </Window>


    C#:
    using System;
    using System.ComponentModel;
    using System.Windows;
    
    namespace SxApp
    {
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            private string buttonColor1;
            public string ButtonColor1
            {
                get => buttonColor1;
                set
                {
                    buttonColor1 = value;
                    OnPropertyChanged("ButtonColor1");
                }
            }
    
            private string buttonColor2;
            public string ButtonColor2
            {
                get => buttonColor2;
                set
                {
                    buttonColor2 = value;
                    OnPropertyChanged("ButtonColor2");
                }
            }
    
            private string buttonPressColor1;
            public string ButtonPressColor1
            {
                get => buttonPressColor1;
                set
                {
                    buttonPressColor1 = value;
                    OnPropertyChanged("ButtonPressColor1");
                }
            }
    
            private string buttonPressColor2;
            public string ButtonPressColor2
            {
                get => buttonPressColor2;
                set
                {
                    buttonPressColor2 = value;
                    OnPropertyChanged("ButtonPressColor2");
                }
            }
    
            public MainWindow()
            {
                InitializeComponent();
                DataContext = this;
                ButtonColor1 = "#db2525";
                ButtonColor2 = "#a944ff";
                ButtonPressColor1 = "#8c5791";
                ButtonPressColor2 = "#32CD32";
            }
    
            private void AesButton_Click(object sender, RoutedEventArgs e)
            {
                string temp = ButtonColor1;
                ButtonColor1 = ButtonColor2;
                ButtonColor2 = temp;
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            public void OnPropertyChanged(string propertyName)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }


    5c5c52d0ec636963645101.png

    Для реализации динамической смены цвета в анимации советовали почитать главу "Рисованные элементы" и "Создание элемента управления лишенного внешнего вида" в книге "Мэтью Мак-Дональд. WPF: Windows Presentation Foundation в .NET 4.0 с примерами на C# 2010 для профессионалов".
    Всем большое спасибо.
    Ответ написан