Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
318 views
in Technique[技术] by (71.8m points)

silverlight - Passing the value of an item selected in a Gridview to the ViewModel of a different Usercontrol

After researching a solution to this for three days, finally I gave up. Now I need your help to solve this.

Scenario:

I've a GridView in a Usercontrol (Lets say WLMSLogs.xaml) and My GridView ItemSource is binded to a List from the ViewModel (WMLSLogsViewModel.cs)

Lets say the List has 4 items (EventID, Name, Request and Response). BothRequest and Responses are XML Strings.

GridView needs to display some of the List items in RowDetailsTemplate under different tab items. So I'm displaying Request and Response under respective TabItems.

<GridView x:Name="WMLSLogGrid" ItemsSource="{Binding WMLSLogModelList}">
<GridView.Columns>      
    <GridViewDataColumn DataMemberBinding="{Binding ID}" Header="ID"/>
    <GridViewDataColumn DataMemberBinding="{Binding UserName}" Header="UserName"/>     
</GridView.Columns>
<GridView.RowDetailsTemplate>
    <DataTemplate >                                                 
            <TabControl>
                <TabItem Header="Request Xml">
                    <TextBlock text="{Binding Request}"/>
                </TabItem>
            <TabItem Header="Response Xml">
                <TextBlock text="{Binding Response}"/>
            </TabItem>
                <TabItem Header="EventLogs" Tag="{Binding .}">
                    <views:LogEvents  />
                </TabItem>
            </TabControl>
        </Grid>
    </DataTemplate>
</GridView.RowDetailsTemplate>

WMLSLogModelList is a Observable collection in WMLSLogsViewModel.cs

So far everything works fine and Grid is displaying data as expected.

Now When User expands any row, he can see two TabItems with request and response. Here I need to add one more TabItem (LogEvents) besides Request and Response tabs.

This LogEvents tab is going have one more GridView to display (so I added a new View <views:LogEvents /> in the tab). Here comes the tricky part.

This LogEvents GridView needs to get the data based on the corresponding Selecteditem (which is EventId), and pass this EventId to a different ViewModel (LogEventViewModel.cs) and binds the data to the Inner GridView dynamically. All this has to happen either as I expand the RowDetails section or if I select the Tab LogEvents.

There is no relation between the data items of these two Grids, except getting the Selected EventId of the main GridView and passing this to a different ViewModel then to Domain service to get the inner GridView Data.

What I did so far

As I mentioned I created a new View UserControl for LogEvents, Placed it under new TabItem(EventLogs) inside row details template of main GridView.

LogEvent UserControl contains a Grid View binded to LogEventsViewModel to get the Collection based on Selected row EventId.

How do I assign the Selected EventId to a new ViewModel and Get the data dynamically?

One Way: As I showed you, I called LogEvents by placing it in side TabItem. whenever I expanded any row, Then It is Initializing the LogEvents page, During that I tried to bind the Datacontext to LogEventsViewModel. But I'm unable to get the Seleted row EventId dynamically. If I get that then I can easily pass it to the LogEventsViewModel constructor.

       var _viewModel = new LogEventsViewModel(EventId);
       this.DataContext = _viewModel;            
       InitializeComponent();

Other way: Pass the selected EventId directly from xaml View binding to that page initialization and then to LogEventsViewModel Something like this

<views:LogEvents  something="{Binding EventId}"/>

Is there any other way to do this?

Details:

LogEvents.xaml

<UserControl.Resources>
    <viewModel:LogEventsViewModel x:Key="ViewModel"/>
</UserControl.Resources>
<Grid DataContext="{Binding Source={StaticResource ViewModel}}">
    <GridView x:Name="LogEventsGrid" ItemsSource="{Binding View}"            
                 <GridView.Columns>
            <telerik:GridViewToggleRowDetailsColumn />              
            <telerik:GridViewDataColumn DataMemberBinding="{Binding EventId}" Header="LogEventId"/>  
            <telerik:GridViewDataColumn DataMemberBinding="{Binding Exception}" Header="Exception" />
        </GridView.Columns>
    </telerik:RadGridView>
</Grid>

LogEvents.xaml.cs

public int EventId
    {
        get { return (int)GetValue(EventIdProperty); }
        set { SetValue(EventIdProperty, value); }
    }
    public static readonly DependencyProperty EventIdProperty =
    DependencyProperty.Register("EventId", typeof(int), typeof(ApplicationLog),
    new PropertyMetadata(0, new PropertyChangedCallback(OnEventIdChanged)));

    private static void OnEventIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {            
        int LogEventId1 = (int)e.NewValue;
        // Need to assign propery in LogEventsViewModel 
    }

LogEventsViewModel.cs

WMLCDomainContext _Context = new WMLCDomainContext();
    private QueryableDomainServiceCollectionView<LogEvents> view;
    public int _eventid;       

    public ApplicationLogsViewModel()
    {
        EntityQuery<LogEvents> getLogEventsQuery = _Context.GetApplicationLogListQuery(EventId);
        this.view = new QueryableDomainServiceCollectionView<ApplicationLog>(_Context, getLogEventsQuery );                        
    }

    public IEnumerable View
    {get {return this.view;}}

    public int EventId
    {
        get{return this._eventid;}
        set{_eventid = value;}
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would create a dependency property on your LogEventsViewModel and then set up a binding on your LogEvents view, something like this:

<views:LogEvents EventId="{Binding EventId}" />

Then in LogEvents.xaml.cs you could create your dependency property:

    private LogEvents_ViewModel _viewModel
    {
        get { return this.DataContext as LogEvents_ViewModel; }
    }

    public string EventId
    {
        get { return (string)GetValue(EventIdProperty); }
        set { SetValue(EventIdProperty, value); }
    }
    public static readonly DependencyProperty EventIdProperty =
        DependencyProperty.Register("EventId", typeof(string), typeof(LogEvents),
        new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnEventIdChanged)));

    private static void OnEventIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((LogEvents)d).OnTrackerInstanceChanged(e);
    }

    protected virtual void OnEventIdChanged(DependencyPropertyChangedEventArgs e)
    {
        this._viewModel.EventId = e.NewValue;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...