diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
index ad43a077396b63b0d4790b1652d893cbe816c69a..dd378dbf9a271b4229988a8481779e614b49e025 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/DataSetMetadataPanel.java
@@ -140,7 +140,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
 
     private final JLabel ownerIdLabel;
 
-    private final JTextField sampleIdText;
+    private final SamplePickerPanel samplePanel;
 
     private final JTextField dataSetIdText;
 
@@ -184,7 +184,9 @@ public class DataSetMetadataPanel extends JPanel implements Observer
 
         // Initialize the fields in the gui
         ownerIdLabel = new JLabel("Owner:", JLabel.TRAILING);
-        sampleIdText = new JTextField();
+        samplePanel =
+                new SamplePickerPanel(mainWindow, clientModel.getExperiments(),
+                        clientModel.getOpenBISService());
         dataSetIdText = new JTextField();
         experimentPicker = new ExperimentPickerPanel(mainWindow, clientModel.getExperiments());
 
@@ -192,7 +194,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
         ownerComboBox = new JComboBox(DataSetOwnerType.values());
 
         ownerIdPanel.add(experimentPicker, DataSetOwnerType.EXPERIMENT.toString());
-        ownerIdPanel.add(sampleIdText, DataSetOwnerType.SAMPLE.toString());
+        ownerIdPanel.add(samplePanel, DataSetOwnerType.SAMPLE.toString());
         ownerIdPanel.add(dataSetIdText, DataSetOwnerType.DATA_SET.toString());
 
         dataSetTypeComboBox = new JComboBox();
@@ -220,7 +222,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
     {
         if (null == newDataSetInfo)
         {
-            sampleIdText.setText(EMPTY_FILE_SELECTION);
+            samplePanel.setText(EMPTY_FILE_SELECTION);
             experimentPicker.setText(EMPTY_FILE_SELECTION);
             updateFileLabel();
             disableAllWidgets();
@@ -240,7 +242,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
                     experimentPicker.setText(builder.getDataSetOwnerIdentifier());
                     break;
                 case SAMPLE:
-                    sampleIdText.setText(builder.getDataSetOwnerIdentifier());
+                    samplePanel.setText(builder.getDataSetOwnerIdentifier());
                     break;
                 case DATA_SET:
                     dataSetIdText.setText(builder.getDataSetOwnerIdentifier());
@@ -285,7 +287,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
     {
         ArrayList<JComponent> editableWidgets = new ArrayList<JComponent>();
         editableWidgets.add(dataSetIdText);
-        editableWidgets.add(sampleIdText);
+        editableWidgets.add(samplePanel);
         editableWidgets.add(experimentPicker);
         editableWidgets.add(dataSetFileButton);
         editableWidgets.add(ownerComboBox);
@@ -379,22 +381,22 @@ public class DataSetMetadataPanel extends JPanel implements Observer
         // The owner row
         ownerIdLabel.setPreferredSize(new Dimension(LABEL_WIDTH, BUTTON_HEIGHT));
 
-        sampleIdText.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
-        sampleIdText.addActionListener(new ActionListener()
+        samplePanel.setPreferredSize(new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT));
+        samplePanel.addActionListener(new ActionListener()
             {
 
                 public void actionPerformed(ActionEvent e)
                 {
-                    setOwnerId(sampleIdText.getText());
+                    setOwnerId(samplePanel.getText());
                 }
 
             });
-        sampleIdText.addFocusListener(new FocusListener()
+        samplePanel.addFocusListener(new FocusListener()
             {
 
                 public void focusLost(FocusEvent e)
                 {
-                    setOwnerId(sampleIdText.getText());
+                    setOwnerId(samplePanel.getText());
                 }
 
                 public void focusGained(FocusEvent e)
@@ -666,7 +668,7 @@ public class DataSetMetadataPanel extends JPanel implements Observer
             case EXPERIMENT:
                 return experimentPicker.getText();
             case SAMPLE:
-                return sampleIdText.getText();
+                return samplePanel.getText();
             case DATA_SET:
                 return dataSetIdText.getText();
         }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java
new file mode 100644
index 0000000000000000000000000000000000000000..862ef6cca1954e9fbbcdbe9efb442a14eacae3dc
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerDialog.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.client.api.gui;
+
+import java.awt.Point;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collections;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.JTree;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.event.TreeExpansionEvent;
+import javax.swing.event.TreeWillExpandListener;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.ExpandVetoException;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import ch.systemsx.cisd.openbis.dss.client.api.gui.tree.FilterableMutableTreeNode;
+import ch.systemsx.cisd.openbis.dss.client.api.v1.IOpenbisServiceFacade;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Sample;
+
+/**
+ * @author Pawel Glyzewski
+ */
+public class SamplePickerDialog extends JDialog implements TreeWillExpandListener
+{
+    private static final long serialVersionUID = 1L;
+
+    private final JTree tree;
+
+    private final JTextField filterField;
+
+    private final JFrame mainWindow;
+
+    private final JOptionPane optionPane;
+
+    private final IOpenbisServiceFacade openbisService;
+
+    private final Timer scheduler = new Timer();
+
+    /**
+     * @param mainWindow
+     * @param experiments
+     * @param openbisService
+     */
+    public SamplePickerDialog(JFrame mainWindow, List<Experiment> experiments,
+            final IOpenbisServiceFacade openbisService)
+    {
+        super(mainWindow, "Pick a sample", true);
+
+        this.mainWindow = mainWindow;
+        this.openbisService = openbisService;
+
+        FilterableMutableTreeNode top = new FilterableMutableTreeNode("Experiments");
+        createNodes(top, experiments);
+        tree = new JTree(top);
+        tree.addTreeWillExpandListener(this);
+        tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+
+        filterField = createFilterField(top, tree);
+
+        optionPane = createOptionPane(filterField, tree, this);
+        this.setContentPane(optionPane);
+    }
+
+    private static JOptionPane createOptionPane(JTextField filterField, final JTree tree,
+            final JDialog parent)
+    {
+        final JScrollPane scrollPane = new JScrollPane(tree);
+
+        Object[] objects = new Object[]
+            { "Filter experiments: ", filterField, "Select Sample:", scrollPane };
+        final JOptionPane optionPane =
+                new JOptionPane(objects, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
+        optionPane.addPropertyChangeListener(new PropertyChangeListener()
+            {
+                public void propertyChange(PropertyChangeEvent evt)
+                {
+                    if (evt.getPropertyName().equals(JOptionPane.VALUE_PROPERTY)
+                            && evt.getNewValue() != null)
+                    {
+                        System.out.println(tree.getSelectionPath().getPath().length);
+                        if (((Integer) evt.getNewValue()).intValue() == JOptionPane.OK_OPTION
+                                && tree.getSelectionPath() == null)
+                        {
+                            JOptionPane.showMessageDialog(parent, "Sample needs to be selected!",
+                                    "No sample selected!", JOptionPane.WARNING_MESSAGE);
+                            optionPane.setValue(optionPane.getInitialValue());
+                        } else if (((Integer) evt.getNewValue()).intValue() == JOptionPane.OK_OPTION
+                                && tree.getSelectionPath().getPath().length < 3)
+                        {
+                            JOptionPane.showMessageDialog(parent,
+                                    "Sample should be selected, not experiment!",
+                                    "No sample selected!", JOptionPane.WARNING_MESSAGE);
+                            optionPane.setValue(optionPane.getInitialValue());
+                        } else
+                        {
+                            parent.setVisible(false);
+                        }
+                    }
+                }
+            });
+
+        return optionPane;
+    }
+
+    private static void createNodes(FilterableMutableTreeNode top, List<Experiment> experiments)
+    {
+        for (Experiment experiment : experiments)
+        {
+            DefaultMutableTreeNode category =
+                    new DefaultMutableTreeNode(experiment.getIdentifier(), true);
+            category.add(new DefaultMutableTreeNode("dummy child"));
+            top.add(category);
+        }
+    }
+
+    private static JTextField createFilterField(final FilterableMutableTreeNode treeNode,
+            final JTree tree)
+    {
+        final JTextField filterField = new JTextField();
+        filterField.setEditable(true);
+        filterField.getDocument().addDocumentListener(new DocumentListener()
+            {
+                public void removeUpdate(DocumentEvent e)
+                {
+                    treeNode.filter(filterField.getText());
+                    ((DefaultTreeModel) tree.getModel()).reload();
+                }
+
+                public void insertUpdate(DocumentEvent e)
+                {
+                    treeNode.filter(filterField.getText());
+                    ((DefaultTreeModel) tree.getModel()).reload();
+                }
+
+                public void changedUpdate(DocumentEvent e)
+                {
+                    treeNode.filter(filterField.getText());
+                    ((DefaultTreeModel) tree.getModel()).reload();
+                }
+            });
+
+        return filterField;
+    }
+
+    public String pickSample()
+    {
+        this.pack();
+
+        int height = this.getHeight() > 500 ? 500 : this.getHeight();
+        int width = this.getWidth() > 600 ? 600 : this.getWidth();
+        this.setSize(width, height);
+
+        Point mwLocation = mainWindow.getLocationOnScreen();
+        int x = mwLocation.x + (mainWindow.getWidth() / 2) - (this.getWidth() / 2);
+        int y = mwLocation.y + (mainWindow.getHeight() / 2) - (this.getHeight() / 2);
+
+        this.setLocation(x > 0 ? x : 0, y > 0 ? y : 0);
+
+        this.setVisible(true);
+
+        Object value = optionPane.getValue();
+        optionPane.setValue(optionPane.getInitialValue());
+        if (value == null || ((Integer) value).intValue() == JOptionPane.CANCEL_OPTION)
+        {
+            return null;
+        } else
+        {
+            return tree.getSelectionPath().getLastPathComponent().toString();
+        }
+    }
+
+    public void treeWillExpand(TreeExpansionEvent event) throws ExpandVetoException
+    {
+        // if top level, then finish
+        if (((TreeNode) event.getPath().getLastPathComponent()).getParent() == null)
+        {
+            return;
+        }
+
+        List<Sample> samples =
+                openbisService.listSamplesForExperiments(Collections.singletonList(event.getPath()
+                        .getLastPathComponent().toString()));
+
+        final DefaultMutableTreeNode node =
+                (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
+
+        node.removeAllChildren();
+        for (Sample s : samples)
+        {
+            node.add(new DefaultMutableTreeNode(s.getIdentifier()));
+        }
+
+        if (node.getChildCount() == 0)
+        {
+            scheduler.schedule(new TimerTask()
+                {
+                    @Override
+                    public void run()
+                    {
+                        tree.collapsePath(new TreePath(node.getPath()));
+                    }
+                }, 1500l);
+        }
+    }
+
+    public void treeWillCollapse(TreeExpansionEvent event) throws ExpandVetoException
+    {
+        DefaultMutableTreeNode node =
+                (DefaultMutableTreeNode) event.getPath().getLastPathComponent();
+
+        node.removeAllChildren();
+        node.add(new DefaultMutableTreeNode("dummy child"));
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerPanel.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerPanel.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3093e8bec0a0dce0fe6730525c22a35033b3084
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/SamplePickerPanel.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.client.api.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusListener;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import ch.systemsx.cisd.openbis.dss.client.api.v1.IOpenbisServiceFacade;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.Experiment;
+
+/**
+ * @author Pawel Glyzewski
+ */
+public class SamplePickerPanel extends JPanel
+{
+
+    private static final long serialVersionUID = 1L;
+
+    private static class JTextFieldFireActionPerformedExposed extends JTextField
+    {
+        private static final long serialVersionUID = -7656053161479466883L;
+
+        @Override
+        public void fireActionPerformed()
+        {
+            super.fireActionPerformed();
+        }
+    }
+
+    private final JTextFieldFireActionPerformedExposed textField =
+            new JTextFieldFireActionPerformedExposed();
+
+    private final JButton button = new JButton("...");
+
+    private final SamplePickerDialog dialog;
+
+    public SamplePickerPanel(final JFrame mainWindow, List<Experiment> experiments,
+            IOpenbisServiceFacade openbisService)
+    {
+        super(new BorderLayout());
+
+        dialog = new SamplePickerDialog(mainWindow, experiments, openbisService);
+        button.setMargin(new Insets(button.getMargin().top, 2, button.getMargin().bottom, 2));
+
+        button.addActionListener(new ActionListener()
+            {
+                public void actionPerformed(ActionEvent e)
+                {
+                    String sampleId = dialog.pickSample();
+                    if (sampleId != null)
+                    {
+                        textField.setText(sampleId);
+                        textField.fireActionPerformed();
+                    }
+                }
+            });
+
+        add(textField, BorderLayout.CENTER);
+        add(button, BorderLayout.EAST);
+    }
+
+    public String getText()
+    {
+        return textField.getText();
+    }
+
+    public void setText(String text)
+    {
+        textField.setText(text);
+    }
+
+    public void addActionListener(ActionListener actionListener)
+    {
+        textField.addActionListener(actionListener);
+    }
+
+    @Override
+    public void addFocusListener(FocusListener focusListener)
+    {
+        textField.addFocusListener(focusListener);
+        button.addFocusListener(focusListener);
+    }
+
+    @Override
+    public void setEnabled(boolean enabled)
+    {
+        textField.setEditable(enabled);
+        textField.setEnabled(enabled);
+        button.setEnabled(enabled);
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..16308fad99feae63748098c9f4d1e413b1c7bc09
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/client/api/gui/tree/FilterableMutableTreeNode.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.client.api.gui.tree;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.regex.Pattern;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
+
+/**
+ * @author Pawel Glyzewski
+ */
+public class FilterableMutableTreeNode extends DefaultMutableTreeNode
+{
+    private static final long serialVersionUID = 1L;
+
+    private static class FilteredEnumerationWrapper implements Enumeration<Object>
+    {
+        private final Enumeration<Object> enumeration;
+
+        private final Pattern pattern;
+
+        private Object next;
+
+        private FilteredEnumerationWrapper(final Enumeration<Object> enumeration,
+                final Pattern pattern)
+        {
+            this.enumeration = enumeration;
+            this.pattern = pattern;
+        }
+
+        public boolean hasMoreElements()
+        {
+            return next != null;
+        }
+
+        public Object nextElement()
+        {
+            if (next == null)
+            {
+                return enumeration.nextElement();
+            }
+            final Object ret = next;
+            next = null;
+
+            while (enumeration.hasMoreElements())
+            {
+                final Object tmp = enumeration.nextElement();
+                if (pattern.matcher(tmp.toString()).find())
+                {
+                    next = tmp;
+                    break;
+                }
+            }
+
+            return ret;
+        }
+    }
+
+    private Pattern pattern = Pattern.compile(".*");
+
+    private ArrayList<Object> filtered = new ArrayList<Object>();
+
+    public FilterableMutableTreeNode(Object nodeValue)
+    {
+        super(nodeValue);
+
+        filter(".*");
+    }
+
+    private synchronized Pattern getPattern()
+    {
+        return this.pattern;
+    }
+
+    private synchronized void setPattern(Pattern pattern)
+    {
+        this.pattern = pattern;
+    }
+
+    private synchronized ArrayList<Object> getFiltered()
+    {
+        return this.filtered;
+    }
+
+    private synchronized void setFiltered(ArrayList<Object> filtered)
+    {
+        this.filtered = filtered;
+    }
+
+    public void filter(String filter)
+    {
+        @SuppressWarnings("hiding")
+        Pattern pattern;
+
+        try
+        {
+            pattern = Pattern.compile("(?i)" + filter);
+        } catch (RuntimeException e)
+        {
+            pattern = Pattern.compile(".*");
+        }
+        setPattern(pattern);
+
+        filter(pattern);
+    }
+
+    public void filter(@SuppressWarnings("hiding") Pattern pattern)
+    {
+        @SuppressWarnings("hiding")
+        ArrayList<Object> filtered = new ArrayList<Object>();
+        @SuppressWarnings("unchecked")
+        Enumeration<Object> enumeration = super.children();
+        while (enumeration.hasMoreElements())
+        {
+            Object o = enumeration.nextElement();
+            if (pattern.matcher(o.toString()).find())
+            {
+                filtered.add(o);
+            }
+        }
+        setFiltered(filtered);
+    }
+
+    @Override
+    public TreeNode getChildAt(int childIndex)
+    {
+        @SuppressWarnings("hiding")
+        final ArrayList<Object> filtered = getFiltered();
+
+        if (filtered == null)
+        {
+            throw new ArrayIndexOutOfBoundsException("node has no children");
+        }
+        return (TreeNode) filtered.get(childIndex);
+    }
+
+    @Override
+    public int getChildCount()
+    {
+        @SuppressWarnings("hiding")
+        final ArrayList<Object> filtered = getFiltered();
+
+        if (filtered == null)
+        {
+            return 0;
+        } else
+        {
+            return filtered.size();
+        }
+    }
+
+    @Override
+    public int getIndex(TreeNode aChild)
+    {
+        if (aChild == null)
+        {
+            throw new IllegalArgumentException("argument is null");
+        }
+
+        if (!isNodeChild(aChild))
+        {
+            return -1;
+        }
+        return getFiltered().indexOf(aChild); // linear search
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Enumeration<Object> children()
+    {
+        return new FilteredEnumerationWrapper(super.children(), getPattern());
+    }
+
+    @Override
+    public void add(MutableTreeNode o)
+    {
+        super.add(o);
+        filter(getPattern());
+    }
+}