[WPF] Jak dać fokus TreeView w model-view (MVVM)?

0

Gdy chcę dać fokus jakieś kontrolce na przykład przy aktywacji okna, to jest prosto
private void Window_Activated(object sender, EventArgs e)

     {
         combo.Focus();
     }

Gorzej, gdy chcę to zrobić z modelu.Mam na przykład wstawienie elementu i selekcja:

      TreeNode subNode = new TreeNode(name);
       subNode.ImageIndex = 0;
       int targetIndex = node.Children.Count;
       node.Insert(targetIndex, subNode);
       node.IsExpanded = true;
       subNode.IsSelected = true;

gdzie

       <TreeView.ItemContainerStyle>
            <Style TargetType="TreeViewItem">
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected}"/>
                <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded}"/>
            </Style>
        </TreeView.ItemContainerStyle>

IsSelected,IsExpanded to property mojego TreeNode.
Ale mimo selekcji nie widać że element jest podświetlony, bo całe drzewko nie ma fokusu. Jak to zrobić?

0

Używanie zdarzeń z kontrolek raczej mało ma wspólnego z MVVM. To co musisz zrobić to napisać sobie Depencency Property, które będzie ustawiało Ci fokus w odpowiednim momencie. Takie DP przypinasz do kontrolki w XAML.

Zamiast DP możesz zrobić AttachedBehavior, które zbindujesz do komendy wewnątrz swojego viewmodelu. Komenda przy wywołaniu będzie wtedy ustawiała fokus.

Poczytaj o:

  • AttachedBehavior;
  • DepencencyProperty.

Przy wykorzystaniu MVVM code-behind może służyć najwyżej do odpalania zdarzeń wydelegowanych z viewmodelu służących np. do obsługi messageboksów.

0

Odpowiedź: http://stackoverflow.com/questions/6737843/how-to-set-focus-to-textbox-using-mvvm
dałem też w kodzie:

private bool _UserShouldEditValueNow = false;
public bool UserShouldEditValueNow
{
get
{
return _UserShouldEditValueNow;
}
set
{
_UserShouldEditValueNow = value;
OnPropertyChanged("UserShouldEditValueNow");
}
}

0

@Borneq: chodzi o Dependency Property, coś takiego jak tutaj, bo nie chce mi się specjalnie pisać projektu: http://stackoverflow.com/questions/1356045/set-focus-on-textbox-in-wpf-from-view-model-c

0

Grzesiek, dzięki. Jeszcze mam pytanie odnośnie tego samego projektu, w tym wątku,aby nie mnożyć wątków, choć może administrator uzna że lepiej w innym wątku.
Otóż dobrze działa przesyłanie SelectedItem to komendy za pomocą CommandParameter
<Button Command="{Binding RenameCmd}" CommandParameter="{Binding SelectedItem, ElementName=treeView}" Content="Rename" HorizontalAlignment="Left" Margin="128,5,0,0" Grid.Row="4" VerticalAlignment="Top" Width="52"/>
ale jeśli komenda jest w menu, wysyła mi nulla

<menuitem header="Find next" inputgesturetext="F3" command="{Binding FindNextCmd}" commandparameter="{Binding SelectedItem, ElementName=treeView}" />

wyśle nulla nawet

<menuitem header="Find" inputgesturetext="Ctrl F" command="{Binding FindCmd}" commandparameter="{Binding RelativeSource={RelativeSource &lt;/blockquote">

Mode=FindAncestor, AncestorType={x:Type Window}}}" />
Jak zrobić przesyłanie selectedItem do komendy szukania?

0

Ale przecież to co robisz jest kompletnie bez sensu. Czemu przesyłasz całe kontrolki do viewmodelu? Tak się nie robi. Przesyłaj jedynie klasę reprezentującą np. wybrany wiersz ale nie całą kontrolkę.Tak to robisz nic innego jak tylko tworzysz sobie drugie code-behind.

0

Przesyłam nie TreeView, tylko chcę przesyłać jedno TreeNode, które jest nie związane z widokiem. Zauważyłem coś ciekawego: gdy wołam z menu jest dobrze, a gdy wołam za pomocą skrótu ^F - jest źle.
To rozwiązuje:

<Window.InputBindings>
    <KeyBinding Modifiers="Control"
                Key="F"
                CommandParameter="{Binding SelectedItem, ElementName=treeView}"
                Command="{Binding FindCmd}" />
</Window.InputBindings>
0

Dorób sobie DependencyProperty i wykorzystaj do bindowania wybranego noda. Tam rzeczywiście wybrany węzeł jako jest tylko do odczytu i nie można go bezpośrednio binować ale DP powinno pomóc. http://stackoverflow.com/questions/1000040/data-binding-to-selecteditem-in-a-wpf-treeview

Oczywiście można przesłać to jako parametr ale wtedy musisz sobie zdefiniować klasę implementującą ICommand, która będzie wykonywać komendy z viewmodelu z parametrem, którym będzie object. Taki parametr można przekonwertować na docelowy typ wewnątrz komendy. Poszukaj w necie informacji o MVVM RelayCommand with parameters. Hasła, których nie można bindować ze względów bezpieczeństwa przesyła sie do viewmodelu w ten sposób.

0

Czy to też pomoże w takich rzeczach jak dodawanie napisu do combo po wyszukaniu? Obecnie mam okienka dialogowe, które korzystają z biblioteki MvvmDialogs korzystającej z GalaSoft.MvvmLight.
W xaml mam <ComboBox x:Name="combo" IsEditable="True" Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}" Margin="10,10,10,8"/>
podobnie robię bindowanie wartości radiobuttonów.
Ale to co chciałbym zrobić: Rozpoczynam wyszukiwanie: pokazuje się dialog z combo, wpisuję do dialogu, to powinno znaleźć się w combo. Najlepiej aby wcześniej wyszukał czy występuje, gdy występuje - skasował a potem dodał na początek. Czy jakiś trigger by pomógł?

0

UpdateSourceTrigger=PropertyChanged oraz powiązane z tym wywołanie OnPropertyChanged (czyli tak naprawdę implementacja INotifyPropertyChanged) wiąże się z aktualizacją widoku na kierunku viewmodel => widok. Jeżeli więc będziesz chciał definiować treść z poziomu viewmodelu to tak, pomoże.

1 użytkowników online, w tym zalogowanych: 0, gości: 1