开发者

WPF buttons are outside the datacontext and could not be bound

开发者 https://www.devze.com 2023-01-16 06:33 出处:网络
Hello, I have 3 Buttons add,delete,open as RelayCommands in my DocumentViewModel. Below you see how I have bound them. Of course those binding does not work, because the data is set to the ItemsSourc

WPF buttons are outside the datacontext and could not be bound

Hello,

I have 3 Buttons add,delete,open as RelayCommands in my DocumentViewModel. Below you see how I have bound them. Of course those binding does not work, because the data is set to the ItemsSource of the ListBox and the buttons are outside of that...

What I tried then is to set the DataContext at the first StackPanel you see in my code snippet.

like this: <StackPanel DataContext="{Binding DocumentViewModelList}" >

BUT then a new problem arised... now the documents are NOT visible/listed anymore in the ListBox :/

How can I make BOTH working?

<StackPanel Orientation="Vertical" >
                                            <ListBox 
                                                Height="100"
                                                Width="Auto"
                                                Focusable="True"
                                                ScrollViewer.HorizontalScrollBarVisibility="Auto" 
                                                ScrollViewer.VerticalScrollBarVisibility="Auto" 
                                                Grid.Row="1" 
                                                Name="itemListBox"
                                                BorderThickness="1"      
                                                ItemsSource="{Binding DocumentViewModelList}"
                                                >
                                                <ListBox.ItemTemplate>
                                                    <DataTemplate>
                                                        <StackPanel>      
                                                            <!-- xxx -->
                                                            <TextBlock Text="{Binding Path=Name}" />
                                                        </StackPanel>
                                                    </DataTemplate>
                                                </ListBox.ItemTemplate>
                                                <ListBox.ItemContainerStyle>                                                  
                                                        <Style TargetType="{x:Type ListBoxItem}">
                                                            <Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}" />
                                                        </Style>                                                  
                                                </ListBox.ItemContainerStyle>
                                            </ListBox>
                                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">                                                
                                                <Button Command="{Binding DeleteDocumentCommand}" HorizontalContentAlignment="Stretch" HorizontalAlignment="Stretch" Content="Delete" />
                                                <Button Command="{Binding    AddDocumentCommand}" HorizontalAlignment="Stretch" Content="Add" />
                                                <Button Command="{Binding   OpenDocumentCommand}" HorizontalAlignment="Stretch" Content="Open" />                                               
                                            </StackPanel>
                                        </StackPanel>

UPDATE:

I tried this:

 <Button Command="{Binding Path=DeleteDocumentCommand, RelativeSource={RelativeSource AncestorType={x:Type DocumentViewModel}}}"

and got this: The type reference cannot find a public type named 'DocumentViewModel'

I would like to stick with the StackPanel DataContext solution and make somehow the ListBox.ItemsSource grabbing the DocumentViewModelList via RelativeSource binding with FindAncestor. I tried some things but no luck, maybe someone can post a nice snippet :)

OK I found the solution: <ListBox ItemsSource="{Binding}" ...

this is binding to the current DataContext that is "DocumentViewModelList" cool!

UPDATE 2:

ok there is still another problem, maybe if someone can provide a solution on this I mark this thread as a solution then. Do not want to open a new thread, because the whole text+code snippet is the same... Problem now is =>Selecting The 1st Document activates the Button. Selecting any other Button does not activate a Button, WHY? What is wrong with the binding of my IsSelected property ?

DocumentViewModel.cs:

private bool _isSelected;
        public bool IsSelected 
        {
            get { return _isSelected; }
            set
            {
                if (_isSelected == value)
                    return;

                _isSelected = value;
                this.RaisePropertyChanged("IsSelected");
            }
        }  

UPDATE 2:

This is the code for enabling the buttons: What do I wrong? I get no binding errors in the output console!?

private void DeleteDocument()
        {
            throw new NotImplementedException();
        }

        private bool CanDeleteDocument()
        {
            return (IsSelected == true);
        }

        private void AddDocument()
        { 

        }

        private void OpenDocument()
        { 

        }

        public Rel开发者_StackOverflow中文版ayCommand DeleteDocumentCommand
        {
            get { return _deleteDocumentCommand ?? (_deleteDocumentCommand = new RelayCommand(() => DeleteDocument(), () => CanDeleteDocument())); }
        }

        public RelayCommand AddDocumentCommand
        {
            get { return _addDocumentCommand ?? (_addDocumentCommand = new RelayCommand(() => AddDocument())); }
        }

        public RelayCommand OpenDocumentCommand
        {
            get { return _openDocumentCommand ?? (_openDocumentCommand = new RelayCommand(() => OpenDocument())); }
        }


Is the DocumentViewModelList a property of your DocumentViewModel?

Typically, what I would have is a ViewModel for that window which would expose an ObservableCollection<T> where T is what you want displayed in the list. Then, you can assign the Window/Page/etc.'s DataContext to the ViewModel, and then bind the ItemsSource of the ListBox to that ObservableCollection<T> property.

For example, here would be a snippet of my ViewModel.

public class SomeViewModel
{
  public ObservableCollection<SingleDocumentViewModel> Docs {get; private set; }

  // other properties can go here
}

In the code-behind for the XAML, (I usually do it in the constructor), you can set its DataContext to a new instance of your ViewModel

public AwesomeDocumentList()
{
  this.DataContext = new SomeViewModel();
  // the rest of the constructor
}

With the Window's DataContext set, you can bind the ItemsSource to the exposed property (I called it Docs)

<ListBox ItemsSource="{Binding Docs}" ... />

Hope that helps.

Update

In the RelayCommand for the button, do you have something specified for the CanExecute predicate? If not, then I believe the RelayCommand will default to always enabled. But if you have a predicate specified, take a look in there.

The code you posted for the IsSelected property looks fine. Looks like the problem lies elsewhere.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号