【问题标题】:Bind mouseLeftButtonDown for ListBoxItem and background color on PropertyChanged (mvvm, wpf)为 ListBoxItem 绑定 mouseLeftButtonDown 和 PropertyChanged 上的背景颜色(mvvm,wpf)
【发布时间】:2016-09-04 03:38:42
【问题描述】:

很抱歉,如果您认为这是与另一篇文章的重复,但我尝试了所有可能的解决方案,但无法成功。

这个问题是两个部分的,但它是关于相同的代码,所以我想我可以在同一个线程中问这个问题。

我尝试使用没有任何(硬编码)耦合的 mvvm 在 C#、wpf、vs2015 中进行排序系统。我需要做两件事。首先是触发我需要在 ViewModel 中捕获的事件,其次,当文章数量超过一定级别时,该文章的列表框的背景应该是绿色(否则为白色/灰色)

为此,我使用了一个 ListBox 和一些 listBoxItems。

MainWindow.xaml(重要的部分)

        <Window x:Class="Sequence_Application_2.GUI.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:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:acb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
        mc:Ignorable="d"
        ....
    <Window.DataContext>

<Grid Grid.Column="0" Margin="10">
                <ListBox x:Name="LstViewFlows" SelectedItem="{Binding SelectedFlow.Name}" ItemsSource="{Binding Flows.Keys}" >
                    <ListBox.ItemContainerStyle>
                        <Style TargetType="{x:Type ListBoxItem}" >
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding SelectedFlow.CanDeliver, UpdateSourceTrigger=PropertyChanged}" Value="true" >
                                    <Setter Property="ListBoxItem.Background" Value="DarkGreen" />
                                    <Setter Property="FontWeight" Value="Bold"/>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ListBox.ItemContainerStyle>
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="MouseLeftButtonDown">
                            <i:InvokeCommandAction Command="{Binding SetSelectedCommand}"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </ListBox>
            </Grid>

问题 1)

当我单击列表框中的列表框项时,我需要将命令绑定到“MouseLeftButtonDown”事件。我尝试了 ACB 解决方案,但无法正常工作。最后我尝试了上面的代码,当我点击一个项目时我无法触发它,但在项目下方,在列表框的空白部分(不是在列表框项目上),它应该会触发。我想我需要重新排列我的 xaml 文件或其他东西,但我尝试了两天,但似乎没有任何效果。

命令名为“setSelectedCommand”,实现方式如下

internal class SetSelectedFlowCommand : ICommand
{
    private FlowsViewModel _flowsViewModel;

    public SetSelectedFlowCommand(FlowsViewModel flowsViewModel)
    {
        _flowsViewModel = flowsViewModel; 
    }

    /// <summary>
    /// 
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _flowsViewModel.SetSelectedFlow();
    }
}

正如我所说,如果我点击 ListBoxItem - 什么都没有发生,但如果我点击 ListBox - 命令被触发(但没有“选择”)

问题 2

正如您在上面的 xaml 中看到的,我尝试根据存储在 ViewModel 中的字典中的对象中的 .CanDeliver 值设置 ListBoxitem 的背景颜色。变量 Flow 是字典, SelectedFlow 应该是被选择的流。

这是一个订单系统,CanDeliver 是一个变量,告诉操作员/用户是否有足够的产品交付给客户。如果有足够的列表框项应该是绿色的,否则保持白色/灰色。你明白我的问题吗?我可以这样做吗?引用字典中的对象? (它由对象中的 INotifyPropertyChanged 触发)

希望你能帮助我,因为我现在已经没有头发要拔了 ;-)

【问题讨论】:

  • 应该是 Property="Background" 而不是 Property="ListBoxItem.Background" 对吧?
  • 你可以写两种方式,即使“ListBoxItem.Background”是多余的

标签: c# wpf xaml mvvm listbox


【解决方案1】:

如果您只想获取 selectedItem,则无需使用事件处理程序。我已经为您构建了一个工作示例,以展示如何使用仅绑定 (MVVM) 来满足您在问题中的要求:

C#(视图模型):

using System;
using System.Collections.Generic;
using System.Windows;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            MyViewModel mvm = new MyViewModel()
            {
                Flows = new ObservableCollection<Flow>() 
                { 
                    new Flow() { Name = "Flow1" }, 
                    new Flow() { Name = "Flow2" }, 
                    new Flow() { Name = "Flow3" , Amount=1}, 
                    new Flow() { Name = "Flow4" } 
                }
            };
            this.DataContext = mvm;
        }
    }

    public class MyViewModel : ObservableObject
    {
        private Flow _selectedflow;
        public ObservableCollection<Flow> Flows
        {
            get;
            set;
        }

        public Flow SelectedFlow
        {
            get { return _selectedflow; }
            set
            {
                if (value != _selectedflow)
                {
                    _selectedflow = value;
                    RaisePropertyChanged("SelectedFlow");
                }
            }
        }
    }

    public class Flow : ObservableObject
    {
        private string _name;
        private int _amount;
        public string Name
        {
            get { return _name; }
            set
            {
                if (value != _name)
                {
                    _name = value;
                    RaisePropertyChanged("Name");
                }
            }
        }

        public bool CanDeliver
        {
            get
            {
                return Amount > 0;
            }
        }

        public int Amount
        {
            get { return _amount; }
            set
            {
                if (value != _amount)
                {
                    _amount = value;
                    RaisePropertyChanged("Amount");
                    RaisePropertyChanged("CanDeliver");
                }
            }
        }
    }

    public class ObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected void RaisePropertyChanged(String propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
    }
}

XAML:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="300" Width="350">
    <Grid>
        <StackPanel Orientation="Vertical">
        <ListBox SelectedItem="{Binding SelectedFlow}" ItemsSource="{Binding Flows}" DisplayMemberPath="Name">
            <ListBox.ItemContainerStyle>
                <Style TargetType="{x:Type ListBoxItem}" >
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding CanDeliver, UpdateSourceTrigger=PropertyChanged}" Value="true" >
                            <Setter Property="Background" Value="DarkGreen" />
                            <Setter Property="FontWeight" Value="Bold"/>
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ListBox.ItemContainerStyle>
        </ListBox>
        <TextBlock Text="{Binding SelectedFlow.Name}"/>
        </StackPanel>
    </Grid>
</Window>

结果:您可以看到带有CanDeliver = True (Amount&gt;0) 的Flow 项目具有绿色背景。 TextBlock 显示 SelectedFlow

【讨论】:

  • 哦,这完全符合预期!太感谢了。如果有足够的代表,我会赞成你的回答。 :-)
  • 别担心@ZombieGoose,只是想为你节省一些头发:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-27
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-16
相关资源
最近更新 更多