Doesn't work well with MVVM scheme.

Apr 15, 2010 at 10:17 PM

I have been trying to modify it. But, in essence. If you try and add an object to the collection and have a datatemplate for that object it will render but you can not change tabs or use transition effects. I have altered the code to allow for moving between tabs by changing the following in the FatTabControl.cs file:

 

protected override void OnSelectionChanged(SelectionChangedEventArgs e)

        {

            //have to check _itemsChanging for performance reasons, otherwise this method

            //gets called when we force renders for adding/removing tabs, and then we're constantly'

            //updating the snapshots WAY more than we need to.

            if (this.ShowContentsTab && !_itemsChanging)

            {

                if (this.ItemsSource != null)

                {

                    //juggle the parents of our hidden stackpanel that gets stuffed into

                    //the hidden contentpresenter

                    if (e.AddedItems.Count > 0)

                    {

                        this.HiddenContent.Children.Remove(e.AddedItems[0] as FrameworkElement);

                    }

 

                    base.OnSelectionChanged(e);

 

                    if (e.RemovedItems.Count > 0)

                    {

                        FrameworkElement mElement = null;

                        if (e.RemovedItems[0] is FrameworkElement)

                            mElement = e.RemovedItems[0] as FrameworkElement;

                        else

                            mElement = new ContentControl { Content = SelectedContent } as FrameworkElement;  

 

                        HiddenContent.Children.Add(mElement);

                    }

                }

 

                //this only needs to happen if we are in this method because the user actually

                //change the tab they selected, and not when new items are added or removed

                //to the collection and ForceRenderItems  (which forces selection of all items)

                //is called from OnItemsChanged---thus the _itemsChanging check above

                UpdateContentsTabViewsIfNecessary();

            }

           

            base.OnSelectionChanged(e);

 

        }

 

The problem I have is:

1. Transition affects don't work because the bound item is not a framework element.

2. The HiddenContent.Children.Add(..) seems to throw an error because the itme already exists.


Coordinator
Apr 16, 2010 at 1:07 AM

orcities,

Hey, thanks for the heads up on this.  At the time I first started building this control I wasn't into MVVM as much as I am now.  If you have a simple example solution that you could zip up which illustrates this problem that would be very helpful for me.

If not, I will try to bind ItemsSource to a trivial domain object and create a trivial datatemplate for that object in an attempt to duplicate what you are seeing.  I think this gap you've found illustrates how insufficient my little sample app is.

I hope to work on this tomorrow morning a bit, I've put off doing things on FabTab for too long.

Thanks,

Josh

Apr 16, 2010 at 1:34 AM

Here is a link to the zip.

When you run it click the button to OpenItemSource. Then click the add tab button. You can then go to the tab but when you try and switch it throws the error. I did get it to load originally but when I did the thumbnail was not consistent with the others.

This is VS2010. You can easiy recreate it in VS08 if needed.

Coordinator
Apr 16, 2010 at 1:38 AM

Awesome!  Thanks, I will look at this and get back to you.

Josh

Coordinator
Apr 16, 2010 at 8:52 PM

orcities,

This is a bit of a tricky issue.  I have some ideas but some of the changes I've made to get past the issue you are describing ripple through and break other features (ie, the rich tooltips).  I have made this my top priority as I have a lot of passion for MVVM and the ability to write code that follows best practices like separation of presentation from representation.

I will keep you posted on this.  My first thought was to do what you had done with the code, but that breaks in many other places in the system as FabTabControl expects FabTabItem.Content to be a FrameworkElement.  If you are needing an immediate hackish workaround you could make your domain objects extend that class, but that is very ugly.

I've since changed HiddenContent to be an ItemsControl rather than a StackPanel.  This allows it to have non-UI "children" added to its ItemsCollection.  But this does break rich tooltips down the line as well as some other features.  I'm definitely still working on this.

Thanks,

Josh

Apr 16, 2010 at 11:58 PM

So I can get it to work if I change the StackPanel with a ItemsControl. The only thing that won't work at this point is tooltips. I can deal with that until you are done.

Sounds good tx. I am new to wpf and not much of a Graphics programmer. I like backend myself. Have you thought about implementing the transition control?

Apr 21, 2010 at 9:20 PM

Do you think you can send me what you have. I really don't care at this point if the tooltips don't work.

Coordinator
Apr 26, 2010 at 9:30 PM
orcities, What I have isn't really worth even playing with at this point. I'm having issues with the screenshot renderings being sized differently for model objects that are visualized via DataTemplates. Also I've been on vacation for the last week so I haven't had much time to work on it. I have a few days this week so I will see what I can come with.
Apr 26, 2010 at 9:41 PM

That would be appreciated. Tx

Coordinator
Apr 28, 2010 at 8:11 PM
Hi orcities,

So I've finally made some progress wih this. As far as I can tell the only remaning feature which is missing is the transitional animations, which I hope to work on tomorrow and possibly Friday.

When you run sampleproject you'll notice a new button called MVVM window which basically does what you were doing. One thing you'll notice in the XAML for MVVM window was that in order to get the snapshots looking good on the content tab screen I had to set some reasonable minimum heights and widths on the containing StackPanel for my DataTemplate.

I've zipped up the files and attached them to this email. Once I've fixed the broken transitional animations I'll commit my changes and there will be a new changset. Please kick the tires on the attached files and let me know how it works for you.

Thanks,

Josh


From: [email removed]
To: [email removed]
Date: Wed, 21 Apr 2010 14:20:46 -0700
Subject: Re: Doesn't work well with MVVM scheme. [fabtab:209488]

From: orcities
Do you think you can send me what you have. I really don't care at this point if the tooltips don't work.
Read the full discussion online.
To add a post to this discussion, reply to this email (fabtab@discussions.codeplex.com)
To start a new discussion for this project, email fabtab@discussions.codeplex.com
You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.
Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com
Coordinator
Apr 28, 2010 at 8:12 PM

Hi orcities,

I've got some code for you to try it.  It's mostly ready to go.  Check your email, I sent it as an attachment.  If you don't get it for some reason, reply to this thread.

Thanks,

Josh

Apr 28, 2010 at 8:13 PM

There is no attachment to this email. And tx for you work.

Coordinator
Apr 28, 2010 at 8:14 PM
I think the problem is that codeplex is acting as an intermediary and not sending on the attachment. Can you give me an actual email address where I can send it?

Josh


From: [email removed]
To: [email removed]
Date: Wed, 28 Apr 2010 13:13:10 -0700
Subject: Re: Doesn't work well with MVVM scheme. [fabtab:209488]

From: orcities
There is no attachment to this email. And tx for you work.
Read the full discussion online.
To add a post to this discussion, reply to this email (fabtab@discussions.codeplex.com)
To start a new discussion for this project, email fabtab@discussions.codeplex.com
You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.
Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com
Apr 28, 2010 at 8:16 PM
Edited Apr 28, 2010 at 8:20 PM

email removed

Apr 29, 2010 at 8:28 PM

I am still having issues.

1. Can't do any transition affects. Content.Opacity or Content.Margins throw error because the ViewModel is not of FrameworkElement

2. Initial Load of tab does not show. I have to click on the tab to make it visible.

3. When I add my second tab of that same base type, in my case I have WorkspaceViewModel, it throws an error in the AddContentsTab() this.ItemSource = items:

The value "FabTab.ContentTabView" is not of type "....ViewModel.WorkspaceViewModel" and cannot be used in this generic collection.
Parameter name: value

Coordinator
Apr 29, 2010 at 10:19 PM

Hi orcities,

Check your email, I sent you a new code drop.  I figured out a workaround for #1 which I demonstrate.  I haven't committed it yet because I need to figure out how I want to handle the default transition effect going forward.

I also fixed #2.

#3 I could not reproduce.  If it's still a problem, please reply to my email with more details.

Thanks,

Josh

Aug 23, 2011 at 11:52 AM

Hey Josh

Can you pls send me this build of fabtabs with MVVM improvements.

Thanks

 -Futurix

Coordinator
Aug 23, 2011 at 12:06 PM

Futurix,

Click on the Source Code tab, then download the latest changeset, which is 58397.  It works better with MVVM.

Josh

Sep 17, 2011 at 11:08 AM

Hi,

I like the look of this control and would like to use it but I am having the same problems as orcities. I have downloaded the latest code (58397) but have the following problems:

  • When I add an item to my observable collection it is not displayed.
  • When I add a second item I get the error "FabTab.ContentTabView" is not of type "....ViewModel.WorkspaceViewModel" and cannot be used in this generic collection". This occurs in the "AddContentsTab()" function. The _tabControl.ItemsSource originally is of type "ViewModel.WorkspaceViewModel" but the function _tabControl.GetContentsTab() returns type "FabTab.ContentTabView" causing the error. This is as far as I have got.

 Below are the templates I am using:

   <DataTemplate x:Key="TabItemTemplate">
    <DockPanel Width="140">
      <Button
        Command="{Binding Path=CloseCommand}"
        Cursor="Hand"
        BorderBrush="Transparent"
        Background="Transparent"
        DockPanel.Dock="Right"
        Focusable="False"
        FontFamily="Courier"
        FontSize="10"
        FontWeight="Bold" 
        Margin="0,1,0,0"
        Padding="0"
        VerticalContentAlignment="Bottom"
        ToolTip="Close this tab"
        Width="20" Height="20">
        <Image Source="{StaticResource RedCross}"/>
      </Button>
      <Button
        Command="{Binding Path=SaveCommand}"
        Width="20" Height="20"
        BorderBrush="Transparent"
        Padding="0"
        BorderThickness="0"
        ToolTip="Save any changes made in this tab"
        DockPanel.Dock="Right">
        <Image Source="{StaticResource Disk}"/>
      </Button>
      <TextBlock Text="{Binding DisplayName}" TextWrapping="Wrap"/>
      <!--<ContentPresenter
        Content="{Binding Path=DisplayName}"
        VerticalAlignment="Center" />-->
    </DockPanel>
  </DataTemplate>


 <DataTemplate x:Key="WorkspacesTemplate">
    <PCVBControls:FabTabControl
      IsSynchronizedWithCurrentItem="True"
      ItemsSource="{Binding}"
      MaxHeight="{Binding RelativeSource={RelativeSource AncestorType=ContentControl},
      Path=ActualHeight}"
      ItemTemplate="{StaticResource TabItemTemplate}"
      Margin="4" />
  </DataTemplate>

Note that my code works with a standard TabControl.

Thanks for any help you can offer.

 

Coordinator
Sep 17, 2011 at 1:14 PM

So the Exception your getting is because the way FabTab works is that when you bind FabTabControl to ItemsSource it is behind the scenes adding in the ContentTab to the underlying collection when necessary. 

What that means is that your ItemsSource collection cannot be bound to an ObservableCollection<WorkspaceViewModel>.  In order for your WorkspaceViewModel and the ContentTabView (which subclasses UserControl) to be in the same generic collection you have to either make ContentTabView implement the same interface as WorkspaceViewModel and have your ObservableCollection<> be of that interface, make WorkspaceViewModel subclass UserControl and make your ObsevableCollection<UserControl> or, use ObservableCollection<object>.

Yes, it's kind of lame, but it was the easiest way to get that to work with the ItemsSource.  If you don't need the ContentTabView there is a ShowContentTabView propery on the FabTabControl which you can set to false, and then your ObservableCollection has no constraints on its type.

Good luck!

Sep 17, 2011 at 3:49 PM

Hi,

Thanks very much for your quick response. I have updated the ContentTabView to implement IWorkspaceViewModel and used ObservableCollection<IWorkspaceViewModel> and that seems OK now. Unfortunately when I add a second tab now I get the error "Cannot change ObservableCollection during a CollectionChanged event." from the AddContentsTab() function in ItemsSourceStrategy file. I have been trying to track down why this is but to no avail so far. I wonder if you have come across this during your development work?

Thanks

Sep 17, 2011 at 5:16 PM

OK, fixed the ObservableCollection CollectionChanged problem using BlockReentrancy(). Only a few (hopefully minor) issues with the richtooltip scaling and ContentTab template.

Thanks