组合框绑定到自定义视图模型 [英] ComboBox Binding to Custom ViewModel

查看:117
本文介绍了组合框绑定到自定义视图模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个WPF项目。这是我的XAML代码:

 <窗口x:类=MyNamespace.MainWindow
的xmlns =HTTP ://schemas.microsoft.com/winfx/2006/xaml/presentation
的xmlns:L =CLR的命名空间:myNameSpace对象
的xmlns:p =CLR的命名空间:MyNamespace.Properties
的xmlns:X =http://schemas.microsoft.com/winfx/2006/xaml
HEIGHT =500标题={X:静态号码:Resources.Title}WIDTH = 500
WindowStartupLocation =中心屏幕>
< Window.Resources>
< L:BrowsersViewModel X:键=BrowsersViewModel/>
< /Window.Resources>
<画布底色={DynamicResource {X:静态SystemColors.ControlBrushKey}}
的DataContext ={StaticResource的BrowsersViewModel}>
<组合框Canvas.Left =10Canvas.Top =10的DisplayMemberPath =名称
的ItemsSource ={绑定路径=项目}
的SelectedItem ={结合模式=双向,路径=的SelectedItem}
SelectedValuePath =过程WIDTH =379/>
<按钮内容=重新填充Canvas.Right =10
Canvas.Top =10WIDTH =75/>
< /帆布>
< /窗GT;



这是我的ViewModel代码:

  // BrowserInstance是一个简单的结构有两个公共字段:
// 1)的System.Diagnostics.Process过程
// 2)System.String名称
公共密封类BrowsersViewModel:INotifyPropertyChanged的
{
公共事件PropertyChangedEventHandler的PropertyChanged;

私人BrowserInstance m_SelectedItem;
公共BrowserInstance的SelectedItem
{
{返回m_SelectedItem; }

{
如果(!m_SelectedItem =值)
{
m_SelectedItem =价值;
NotifyPropertyChanged(的SelectedItem);
}
}
}

私人的ObservableCollection< BrowserInstance> m_Items;
公众的ObservableCollection< BrowserInstance>项目
{
{返回m_Items; }

{
如果(!m_Items =值)
{
m_Items =价值;
NotifyPropertyChanged(项目);
}
}
}

公共BrowsersViewModel()
{
m_Items =新的ObservableCollection< BrowserInstance>();
填充();
}

私人无效NotifyPropertyChanged(字符串propertyName的)
{
如果(的PropertyChanged!= NULL)
的PropertyChanged(这一点,(新PropertyChangedEventArgs(propertyName的) ));
}

公共无效的填充()
{
的foreach(工艺过程Process.GetProcessesByName(铬))
{
BrowserInstance实例=新BrowserInstance();
instance.Process =进程;
instance.Name =[铬]
+ process.Handle.ToString()
++((process.MainWindowTitle.Length> 0)
过程.MainWindowTitle:NULL);

m_Items.Add(实例);
}

NotifyPropertyChanged(项目);
}
}



我有真的很难次得到这个工作。我在的例子吨到处看,我仍然无法找到一个解决方案,使一切工作正常。



1),我看到里面有很多值的我组合框下拉列表中,但它们都是空的。我想,以显示组合框里面的 BrowserInstance.Name 财产和项目时是检索 BrowserInstance.Process 价值选中。



2)应用程序启动时,支票上当前正在运行的浏览器进程,以填充组合框制成。如果没有找到运行的情况下,我怎么可能我的组合框,如无实例已经找到了!里面显示的消息?



3)如果在应用程序统计数据,我怎么能默认选择第一个被发现的一个或多个浏览器实例?



4)重新填充按钮,以重新检查用户运行浏览器的情况下使用。比方说,以前选择的实例仍在运行...我怎样才能保持一个选择?如果之前选择的情况下,不运行了,我怎么能在默认情况下选中第一个再次? !



非常感谢



编辑:这里是我当前的代码



主窗口:

 公共主窗口()
{
的InitializeComponent();
的DataContext = m_BrowserInstances =新BrowserInstancesViewModel();
}

私人无效OnClickButtonRefresh(对象发件人,RoutedEventArgs E)
{
m_BrowserInstances.Populate();
}



BrowserInstancesViewModel:

 公共无效的填充()
{
BrowserInstance将selectedItem = m_SelectedItem;
名单,LT; BrowserInstance>项目=新的List< BrowserInstance>();

的foreach(在Process.GetProcessesByName工艺过程(铬))
items.Add(新BrowserInstance(过程));

如果(items.Count大于0)
{
m_Items =新的ObservableCollection&所述; BrowserInstance>(items.OrderBy(X => x.Process.Id));

如果((将selectedItem = NULL)及!及(m_Items.SingleOrDefault(NewMethod(将selectedItem))= NULL)!)
m_SelectedItem = selectedItem属性;
,否则
m_SelectedItem = m_Items [0];

m_Enabled = TRUE;
}
,否则
{
m_Items =新的ObservableCollection< BrowserInstance>(){(新BrowserInstance())};
m_SelectedItem = m_Items [0];

m_Enabled = FALSE;
}

NotifyPropertyChanged(已启用);
NotifyPropertyChanged(项目);
NotifyPropertyChanged(的SelectedItem);
}


解决方案

1)我不能重复这个问题,你肯定有一个运行Chrome的过程? :D



2),你可以破解它是这样的::D



 <组合框Canvas.Left =10Canvas.Top =10
的DisplayMemberPath =名称的ItemsSource ={绑定路径=项目}
的SelectedItem ={结合模式=双向,路径=的SelectedItem}
SelectedValuePath =过程WIDTH =200>
< ComboBox.Style>
<风格的TargetType =组合框>
< setter属性=IsEnabledVALUE =真/>
< Style.Triggers>
< DataTrigger绑定={绑定路径= Items.Count}VALUE =0>
< setter属性=IsEnabledVALUE =FALSE/>
< / DataTrigger>
< /Style.Triggers>
< /样式和GT;
< /ComboBox.Style>
< /组合框>
< TextBlock的Canvas.Left =10Canvas.Top =10
文本=没有实例已经找到了! >
< TextBlock.Style>
<风格的TargetType =TextBlock的>
< setter属性=能见度VALUE =折叠/>
< Style.Triggers>
< DataTrigger绑定={绑定路径= Items.Count}VALUE =0>
< setter属性=能见度VALUE =可见/>
< / DataTrigger>
< /Style.Triggers>
< /样式和GT;
< /TextBlock.Style>
< / TextBlock的>

或更好,但你retemplate组合框包含文本块和使用的的hasitems属性值绑定其知名度组合框(ofcourse您将需要使用BoolToVis转换器)



3)添加此代码到虚拟机的构造填充



 如果(m_Items.Count大于0)
{
的SelectedItem = m_Items [0];
}



4)添加新的重新填充方法到VM和存储当前selectedItem属性,填充,检查是否存在与否,重新选择项目

 公共无效重新填充()
{
BrowserInstance currentSelectedItem = m_SelectedItem;
填充();

如果(m_Items.Count大于0)
{
如果(currentSelectedItem = NULL
和!&安培; m_Items.FirstOrDefault
((BI) = GT; bi.Process == currentSelectedItem .Process)
= NULL)
{
的SelectedItem = currentSelectedItem!;
}
,否则
{
的SelectedItem = m_Items [0];
}
}
}



注:结果
我肯定不知道检查什么属性来验证实例的becoz当我试图上面的代码并调试它我Chrome的进程列表不断变化的存在。但基本上那是什么,你可以做


I am working on a WPF project. This is my XAML code:

<Window x:Class="MyNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:l="clr-namespace:MyNamespace" 
        xmlns:p="clr-namespace:MyNamespace.Properties"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
        Height="500" Title="{x:Static p:Resources.Title}" Width="500"
        WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <l:BrowsersViewModel x:Key="BrowsersViewModel"/>
    </Window.Resources>
    <Canvas Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
            DataContext="{StaticResource BrowsersViewModel}">
        <ComboBox Canvas.Left="10" Canvas.Top="10" DisplayMemberPath="Name"
                  ItemsSource="{Binding Path=Items}" 
                  SelectedItem="{Binding Mode=TwoWay, Path=SelectedItem}"
                  SelectedValuePath="Process" Width="379"/>
        <Button Content="Repopulate" Canvas.Right="10" 
                Canvas.Top="10" Width="75"/>
    </Canvas>
</Window>

And this is my ViewModel code:

// BrowserInstance is a simple struct with two public fields:
// 1) System.Diagnostics.Process Process
// 2) System.String Name
public sealed class BrowsersViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private BrowserInstance m_SelectedItem;
    public BrowserInstance SelectedItem
    {
        get { return m_SelectedItem; }
        set
        {
            if (m_SelectedItem != value)
            {
                m_SelectedItem = value;
                NotifyPropertyChanged("SelectedItem");
            }
        }
    }

    private ObservableCollection<BrowserInstance> m_Items;
    public ObservableCollection<BrowserInstance> Items
    { 
        get { return m_Items; }
        set
        {
            if (m_Items != value)
            {
                m_Items = value;
                NotifyPropertyChanged("Items");
            }
        }
    }

    public BrowsersViewModel()
    {
        m_Items = new ObservableCollection<BrowserInstance>();
        Populate();
    }

    private void NotifyPropertyChanged(String propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, (new PropertyChangedEventArgs(propertyName)));
    }

    public void Populate()
    {
        foreach (Process process in Process.GetProcessesByName("chrome"))
        {
            BrowserInstance instance = new BrowserInstance();
            instance.Process = process;
            instance.Name = "[Chrome] " 
                         + process.Handle.ToString() 
                         + " " + ((process.MainWindowTitle.Length > 0) ? 
                                        process.MainWindowTitle : "NULL");

            m_Items.Add(instance);
        }

        NotifyPropertyChanged("Items");
    }
}

I'm having REALLY hard times getting this to work. I've looked at TONS of examples everywhere and I still can't find a solution to make everything work as expected.

1) I see a lot of values inside my ComboBox dropdown, but they are all empty. I would like to display the BrowserInstance.Name property inside the ComboBox and retrieve the BrowserInstance.Process value when an item is selected.

2) When the application starts, a check on the currently running browser processes is made in order to populate the ComboBox. If no running instances are found, how could I display a message inside my ComboBox like "No instances have been found!"?

3) If one or more browser instances are found when the application stats, how can I select the first one by default?

4) The Repopulate button will be used in order to recheck running browser instances by users. Let's say the previously selected instance is still running... how can I keep that one selected? And if the previously selected instances is not running anymore, how can I select by default the first one once again?

Many thanks!

EDIT: HERE IS MY CURRENT CODE

MainWindow:

public MainWindow()
{
    InitializeComponent();
    DataContext = m_BrowserInstances = new BrowserInstancesViewModel();
}

private void OnClickButtonRefresh(Object sender, RoutedEventArgs e)
{
    m_BrowserInstances.Populate();
}

BrowserInstancesViewModel:

public void Populate()
{
    BrowserInstance selectedItem = m_SelectedItem;
    List<BrowserInstance> items = new List<BrowserInstance>();

    foreach (Process process in Process.GetProcessesByName("chrome"))
        items.Add(new BrowserInstance(process));

    if (items.Count > 0)
    {
        m_Items = new ObservableCollection<BrowserInstance>(items.OrderBy(x => x.Process.Id));

        if ((selectedItem != null) && (m_Items.SingleOrDefault(NewMethod(selectedItem)) != null))
            m_SelectedItem = selectedItem;
        else
            m_SelectedItem = m_Items[0];

        m_Enabled = true;
    }
    else
    {
        m_Items = new ObservableCollection<BrowserInstance>() { (new BrowserInstance()) };
        m_SelectedItem = m_Items[0];

        m_Enabled = false;
    }

    NotifyPropertyChanged("Enabled");
    NotifyPropertyChanged("Items");
    NotifyPropertyChanged("SelectedItem");
}

解决方案

1) I can't replicate this issue, are you sure there's a running chrome process? :D

2) you can hack it like this: :D

     <ComboBox Canvas.Left="10" Canvas.Top="10" 
               DisplayMemberPath="Name" ItemsSource="{Binding Path=Items}"
               SelectedItem="{Binding Mode=TwoWay, Path=SelectedItem}" 
               SelectedValuePath="Process" Width="200">
        <ComboBox.Style>
            <Style TargetType="ComboBox">
                <Setter Property="IsEnabled" Value="True"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Items.Count}" Value="0">
                        <Setter Property="IsEnabled" Value="False"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </ComboBox.Style>
    </ComboBox>
    <TextBlock Canvas.Left="10" Canvas.Top="10" 
               Text="No instances have been found!" >
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Visibility" Value="Collapsed"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=Items.Count}" Value="0">
                        <Setter Property="Visibility" Value="Visible"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>

or better yet you retemplate the combobox to include textblock and bind its visibility using the hasitems property value of the combobox (ofcourse you will need to use BoolToVis converter)

3) add this code into the vm constructor after populate

if (m_Items.Count > 0)
{
    SelectedItem = m_Items[0];
}

4) add new repopulate method into the vm and store the current selecteditem, populate, check whether exist or not, reselect the item

    public void Repopulate()
    {
        BrowserInstance currentSelectedItem = m_SelectedItem;
        Populate();

        if (m_Items.Count>0)
        {
            if (currentSelectedItem !=null 
                && m_Items.FirstOrDefault
                   ((bi) => bi.Process == currentSelectedItem .Process) 
                         != null)
            {
                SelectedItem = currentSelectedItem;
            }
            else
            {
                SelectedItem = m_Items[0];
            }
        }
    }

NB:
I'm not sure what property to check to verify the existence of the instance becoz when i tried above code and debug it my chrome' process list keep changing. but basically thats what you could do

这篇关于组合框绑定到自定义视图模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆