Задать вопрос
Ответы пользователя по тегу C#
  • Как обратиться к контролу из VM?

    @sergeyfk Автор вопроса
    Я все таки написал свой костыль, который работает вполне не плохо, но не идеально. Сейчас я все вкратце расскажу...
    Начнем со вспомоготельного класса для вызова комманд:
    public class ActionCommand : ICommand
        {
            private Action _action;
            private Action<object> _actionObj;
            public ActionCommand(Action action)
            {
                _action = action;
            }
            public ActionCommand(Action<object> actionObj)
            {
                _actionObj = actionObj;
            }
            public bool CanExecute(object parameter)
            {
                return true;
            }
            public void Execute(object parameter)
            {
                if (parameter == null)
                {
                    _action?.Invoke();
                }
                else if (parameter is System.Windows.Controls.TextBox)
                {
                    _actionObj?.Invoke(parameter);
                }
            }
            public event EventHandler CanExecuteChanged;
        }

    Думаю тут ничего не стоит объяснять. Описаний подобных классов хватает. Я лишь добавил Action с параметром и проверку параметра на null и тип необходимого мне объекта.

    Идем дальше...
    Нужно к тэгу Window дописать следущий параметр и добавить соответствующую библиотеку, которая есть в nuget
    xmlns:intr="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"


    Далее создадим наш контрол:
    <TextBox Text="{Binding Log, Mode=OneWay}" IsReadOnly="True" Margin="5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
                    <intr:Interaction.Triggers>
                        <intr:EventTrigger EventName="TextChanged">
                            <intr:InvokeCommandAction Command="{Binding command_InitializedTextBox}" 
                                                      CommandParameter="{Binding RelativeSource=
                                                     {RelativeSource
                                                     Mode=FindAncestor,
                                                     AncestorType=TextBox}}"/>
                        </intr:EventTrigger>
                    </intr:Interaction.Triggers>
                </TextBox>

    Обращаю внимание на AncestorType=TextBox. Вам необходимо поменять значение на необходимое вам(как и во вспомогательном классе), а иначе передастся найденный TextBox, если он вообще есть. Отвечаю сразу на ожидаемые вопросы:
    использовать событие Loaded и Initialized не получится в данном случае, т.к. VM объявляется позже, чем срабатывают эти события.

    Ну и идем к скоплению костылей... Во ViewModel
    public ICommand command_InitializedTextBox
            {
                get
                {
                    return new ActionCommand((object sender) => { InitializedTextBox(sender); });
                }
            }
            private void InitializedTextBox(object sender)
            {
                _LogControl = ((System.Windows.Controls.TextBox)sender);
            }

    Тут должно быть все понятно.

    А вот void для добавления текста.
    private void AppendLogText(string getter)
            {
                if (_LogControl != null)
                {
                    _LogControl.AppendText(getter);
                }
                else
                {
                    Log += getter;
                }
            }

    Текст изменяется биндингом только 1 раз.

    Хочу отметить, что использовать данное решение стоит когда используются большие текста. ТекстБокс долго "думает" при использовании больших текстов и биндинга, а при использовании AppendText - нет.
    Ответ написан
    Комментировать
  • Почему вылетает исключение при попытке объявить SQLiteConnection?

    @sergeyfk Автор вопроса
    Решение: подключите System.Windows.Forms
    Ответ написан
    Комментировать